一套通用Ajax框架 .

最近由于项目需要,专心研究了一下Ajax的相关程序设计,本来一开始想用Prototype或者jQuery等框架,后来发现其实用不到这些框架里面的那么多内容,强行使用的话只能拖累我网站的访问者,降低用户体验,因此决定自己写一套适合自己需求的Ajax代码库。
在这套Ajax代码库中,实现了如下的功能:
1、Ajax远程调用数据
2、通过Ajax异步提交Form表单
3、返回数据后,能够将数据绑定到页面的相关控件内(如:div、select、ul、span等等)
4、让Ajax程序支持浏览器的前进、后退按钮
一、什么是Ajax,他都能做什么?
AJAX全称为“Asynchronous JavaScript and XML”(非同步JavaScript和XML),是一种创建互动式网页应用的网页开发技术。
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变过的信息。
Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像DHTML应用程序那样,Ajax应用程序必须在众多不同的浏览器和平台上经过严格的测试。随着Ajax的成熟,一些简化Ajax使用方法的程序库也相继问世。同样,也出现了另一种辅助程序设计的技术,为那些不支持JavaScript的用户提供替代功能。
二、核心代码
所谓核心代码就是提供一个能够跨浏览器的Ajax调用代码,这部分代码是后面扩展代码的必备部分,在这部分代码中我们提供了一个创建XMLHttpRequest对象并能够与Web服务器进行异步数据交换。
在我写的这些代码中,自定义了两个相关的函数,一个是通用的获取HTML对象函数,还有一个就是自动过滤字符串开头结尾的空格,代码如下:
function $( elementId ) {
return document.getElementById(elementId);
}

function trim(str){ //删除左右两端的空格
return str.replace(/(^/s*)|(/s*$)/g,"");
}
Ajax的核心代码如下:
/*
*根据不同的浏览器,获取Ajax对象
*/

function getAjaxObject() {
var xmlHttpRequest;
//判断是否把XMLHttpRequest实现为一个本地javascript对象
if(window.XMLHttpRequest){
xmlHttpRequest = new XMLHttpRequest();
} else if(window.ActiveXObject){ //判断是否支持ActiveX控件
try{
//通过实例化ActiveXObject的一个新实例来创建XMLHttpRequest对象
xmlHttpRequest = new ActiveXObject( "Microsoft.XMLHTTP"); //msxml3以上版本
} catch(e){
try{
//通过实例化ActiveXObject的一个新实例来创建XMLHttpRequest对象
xmlHttpRequest = new ActiveXObject( "Msxml2.XMLHTTP"); //msxml3以下版本
} catch(e){}
}
}
if ( !xmlHttpRequest ) {
alert( "创建Ajax对象失败,您将无法正常浏览网页");
}
return xmlHttpRequest;
}
/*
*异步方式提交请求
*/

function sendRequestByAjax(method,url,data,dataHandler) {
//获取Ajax对象
request = getAjaxObject();
//设置回调函数
if( !IE4 ){
request.onload = dataHandler;
} else {
request.onreadystatechange = dataHandler;
}
request.open(method,true); //true代表使用异步方式 false代表使用同步方式
//处理提交方式
if ( "get" == method.toLowerCase() ) {
//使用GET方式提交数据
var urls = url.split( "?");
if ( urls[1] == "" || typeof(urls[1]) == "undefined" ) {
url = urls[0] + "?" + data;
} else {
url = urls[0] + "?" + urls[1] + "&" + data;
}
data = null; // for GET method,request必须为空

} else if ( "post" == method.toLowerCase() ){
//使用POST方式提交数据
request.setRequestHeader( "Content-Type","application/x-www-form-urlencoded");
}
request.send(data);
}
三、回调函数以及数据解析
根据Ajax提出者Jesse James Garrett建议,Ajax使用XHTML+CSS来表示信息,使用JavaScript操作DOM(Document Object Model)进行动态显示及交互,使用XML和XSLT进行数据交换及相关操作,由于Opera浏览器不支持XSLT格式对象,也不支持XSLT,所以现在一般情况下都是使用XML进行数据传递。
在回调函数中,会出现request的一些相关属性,其代表值如下:
readyState:提供当前 HTML 的就绪状态。
0:请求未初始化
1:请求已经建立,但是还没有发送(还没有调用 send())
2:请求已发送,正在处理中(通常现在可以从响应中获取内容头)
3:请求在处理中,通常响应中已有部分数据可用了
4:响应已完成
status:提供当前HTML的状态码
401:未经授权
403:禁止访问
404:没找到访问页
200:正常
回调函数如下所示:
/*
*返回数据格式为XML的回调函数
*/

function xmlCallBack() {
//数据接收完成
if( request.readyState == 4 ){
//数据正常接收
if( request.status == 200 ){
//调用XML文件解析函数
parseXMLMessage();
} else {
//显示错误信息
alert( "Not able to retrieve description"+request.statusText);
}
}
}
/*
*XML文件解析函数
*/

function parseXMLMessage() {
//获取返回的XML文件
var xmlDoc=request.responseXML.documentElement;
//解析XML文件
parseXML("elementId",xmlDoc);
}
/*
*解析XML文件
*@paramelementId要将数据绑定的对象Id
*@paramxmlDoc要解析的XML文件
*/

function parseXML(elementId,xmlDoc) {
//这里XML文件的格式根据你的自定义,自行修改
var xmlRoot = xmlDoc.getElementsByTagName( "items");
var dataType = xmlRoot[0].getAttribute( "dataType");
var items = xmlDoc.getElementsByTagName('item');
switch ( dataType.toLowerCase() ) {
case "array" :
//返回对象为结果集
bindItems(elementId,items);
break;
case "string" :
//返回对象为字符串
bindText(elementId,items[0].childNodes[0].firstChild.nodeValue);
}
}
如果Ajax调用后返回的是一个HTML页面,则可以使用下面的这个回调函数:
/*
*HTML文件解析函数
*/

function htmlCallBack() {
if( request.readyState == 4 ){
if( request.status == 200 ){
parseHTMLMessage();
} else {
alert( "Not able to retrieve description"+request.statusText);
}
}
}
/*
*解析HTML文件
*/

function parseHTMLMessage() {
//获取返回的HTML代码
var htmlCode = request.responseText;
//绑定HTML代码
bindText("elementId",htmlCode);
}
四、数据绑定
数据绑定根据不同的控件类型,可以使用以下两个数据绑定函数,能够实现绑定select控件、ul无序列表、插入HTML代码等:
/*
*绑定结果集
*/

function bindItems(elementId,items) {
var elem = $(elementId);
//判断要绑定的对象,类型是否匹配
if ( elem.tagName.toLowerCase() != "select" && elem.tagName.toLowerCase() != "ul" ) {
alert( "数据类型不匹配,无法进行数据绑定");
return;
}
//绑定select
if ( elem.tagName.toLowerCase() == "select" ) {
while ( elem.childNodes.length > 0 ) {
//清除现有数据
elem.removeChild(elem.childNodes[0]);
}
// 绑定数据
for ( var i = 0; i < items.length; i++ ) {
var option = document.createElement( "OPTION");
var Data = items[i];

option.value = Data.childNodes[0].firstChild.nodeValue;
option.text = Data.childNodes[1].firstChild.nodeValue;

elem.options.add(option);
}
} else if ( elem.tagName.toLowerCase() == "ul" ) {
//绑定ul列表
elem.innerHTML = "";
// bind data
for ( var i = 0; i < items.length; i++ ) {
var Data = items[i];
var urlAddress = Data.childNodes[0].firstChild.nodeValue;
var showText = Data.childNodes[1].firstChild.nodeValue;
var innerCode = "<li><a href=/"" + urlAddress + "/" title=/"" + showText + "/">" + showText + "</a></li>";
elem.innerHTML += innerCode;
}
}
}
/*
*绑定字符串,也可以实现绑定HTML代码
*/

function bindText(elementId,value) {
var elem = $(elementId);
//分析绑定对象类型
switch ( elem.tagName.toLowerCase() ) {
case "div":
case "span":
case "textarea":
elem.innerHTML = value;
break;
case "input":
elem.value = value;
break;
default:
alert( "数据类型不匹配,无法进行数据绑定");
return;
}
saveHistory(elementId); //保存历史记录用于实现浏览器的前进、后退按钮
}
五、进阶功能——实现Ajax提交Form表单
通过Ajax提交Form有以下两个非常重要的地方:
1、需要解析所有Form中的控件,将控件拼成类似于“?param1=value1&param2=value2......”这样的字符串,然后通过“POST”模式异步提交,将上面拼成的字符串通过request.send(data)发送到服务器。
2、关于文件上传,由于我没有这方面的需求,没有写出一个测试后的代码,但通过查阅相关资料,看到可以通过隐藏IFrame来实现这一功能。
通过Ajax异步提交表单的代码如下:
/*
*通过Ajax异步提交表单
*/

function submitFormByAjax(formId) {
sendRequestByAjax($(formId).method,$(formId).getAttributeNode( "action").value,encodeFormData($(formId)),htmlCallBack);
}
解析Form内控件,并拼成字符串的函数如下:
/*
*分析Form表单数据
*@paramformElementForm对象
*/

function encodeFormData(formElement) {
var whereClause = "";
var and = "";
for ( i = 0 ; i < formElement.length ; i++ ) {
var element = formElement[i];
if ( element.name != "" ) {
if (element.type=='select-one') {
element_value = element.options[element.selectedIndex].value;
} else if ( element.type == 'checkbox' || element.type == 'radio' ) {
if ( element.checked == false ) {
break;
}
element_value = trim(element.value);
} else {
element_value = trim(element.value);
}
whereClause += and + trim(element.name) + '=' + element_value.replace(//&/g,"%26");
and = "&"
}
}
return whereClause;
}
六、进阶功能——实现浏览器的前进、后退按钮
很多人在使用了Ajax技术后会发现,浏览器的前进、后退按钮无效了,大大降低了用户体验,曾经这一点也被作为Ajax技术的弊端而大范围讨论,后来经过不断的尝试,终于实现了这一功能,听起来很简答,就是通过一个隐藏的IFrame,使用JavaScript改变 IFrame的src属性而激活浏览器的前进、后退按钮。再通过一个特殊的JavaScript函数,实现更新页面数据。
具体的代码如下:
var historyValue = new Array(10); //保存记录的最大次数
var historyCount = 0;

/*
*保存历史记录
*@paramelementId要保存的区域ID
*/

function saveHistory(elementId) {
//"historyFrame"隐藏的IFrame的ID属性值
var iframeDocument = $( "historyFrame");
if ( iframeDocument != null ) {
if ( historyCount == 9 ) {
historyCount = 0;
} else {
historyCount++;
}
historyValue[historyCount] = new Array(2);
historyValue[historyCount][0] = elementId;
var element = $(elementId);
historyValue[historyCount][1] = element.innerHTML;
iframeDocument.src = "/history.jsp?" + historyCount;
}
}
/*
*获取历史记录
*@paramhistoryIndex历史记录索引号
*/

function getHistory(historyIndex) {
if ( historyIndex != historyCount ) {
if ( historyValue[historyIndex] ) {
historyCount = historyIndex;
}
var element = $(historyValue[historyCount][0]);
element.innerHTML = historyValue[historyCount][1];
}
}
history.jsp页面中的代码很简单,只有以下代码:
< script >
var url=window.location.href;
if(url.indexOf('?')>-1)
{
parent.getHistory(url.substr(url.indexOf('?')+1));
document.write(window.location.search.substr(1));
}

</script>
在页面最下端记得写上下面的代码:
< iframe id ="historyFrame" name ="historyFrame" src ="/history.jsp?0" height ="0px" frameborder ="no" > </iframe>
七、总结
我认为Ajax的应用最好根据自己的需求,来实现相应的功能,尽量避免JavaScript代码过多,拖累客户端浏览器。由于JavaScript代码设计过于灵活,如果JavaScript程序员水平相当,肯定能够开发出很好的JavaScript程序,如果 JavaScript程序员水平良莠不齐,最好避免多人同时开发一套JavaScript程序,防止JavaScript代码质量降低。
由于JavaScript调试起来非常不方便,建议大家多多使用FireFox浏览器的错误控制台,会给大家提供很多的方便

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


$.AJAX()方法中的PROCESSDATA参数 在使用jQuery的$.ajax()方法的时候参数processData默认为true(该方法为jQuery独有的) 默认情况下会将发送的数据序列化以适应默认的内容类型application/x-www-form-urlencoded 如果想发送不
form表单提交的几种方式 表单提交方式一:直接利用form表单提交 html页面代码: &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset=&quot;UTF-8&quot; /&gt; &lt;title&gt;Ins
文章浏览阅读1.3k次。AJAX的无刷新机制使得在注册系统中对于注册名称的检测能即时显示。常见的用户注册是用户输入用户名,后台程序检测数据库中用户名是否重复而做出注册的成功与失败之提示(当用户注册重名时将返回重新注册),或者稍微人性化一点就是在用户名文本框后添加一个检测按钮,让用户检测后再做注册。以上操作,对于用户体验方面来说是比较“差劲”的,一个很好的用户体验就是:当用户输入完注册用户名后,Web系统应能即时检查并即时_用户注册 实时异步检测
文章浏览阅读1.2k次。 本文将解释如何使用AJAX和JSON分析器在客户端和服务器之间创建复杂的JSON数据传输层。一、 引言毫无疑问,AJAX已经成为当今Web开发中一种强有力的用户交互技术,但是它的许多可能性应用仍然鲜为人知。在本文中,我们将来共同探讨如何 使用JavaScript对象标志(JSON)和JSON分析器在服务器和客户端AJAX引擎之间创建复杂而强有力的JSON数据传输层。我们将_ajax技术可行性
文章浏览阅读2.2k次。/************************** 创建XMLHttpRequest对象 **************************/function CreateRequest(){ var xmlObj = null; try { xmlObj = new XMLHttpRequest(); } catch(e) {
文章浏览阅读3.7k次。在ajax应用中,通常一个页面要同时发送多个请求,如果只有一个XMLHttpRequest对象,前面的请求还未完成,后面的就会把前面的覆盖 掉,如果每次都创建一个新的XMLHttpRequest对象,也会造成浪费。解决的办法就是创建一个XMLHttpRequset的对象池,如果池里有 空闲的对象,则使用此对象,否则将创建一个新的对象。下面是我最近写的一个简单的类:* XMLHttpReques_xmlhttprequest发送多个请求
文章浏览阅读3.1k次。Ajax 同一页面如何同时执行多个 XMLHTTP 呢,比如博客页,需要同时利用 Ajax 读取作者信息、文章信息、评论信息……我们的第一反应可能是创建多个全局 XMLHTTP 对象,但这并不现实。其实实现方式非常简单,就是给 onreadystatechange 对应的回调函数加上参数,以下代码是解决方案中一个函数中的一段代码。xmlhttp.open("GET", "ajax_proc_ajax响应多个mxl文件
文章浏览阅读1.5k次。数据岛指的是存在Html网页中的xml代码段,它在Html中形成了一个数据的集合,数据岛允许我们在Html网页中集成xml,对xml编写脚本.数据岛有它特有的形式,由标记xml开始,在开始标记中要有一个ID属性,用于指定该指定数据岛的名称。 (当然要以/xml结束).元素xml包含的内容就是xml代码。数据岛也分为2种:1)内嵌的数据岛形式2)外嵌的数据岛形式说了那么多废话,还_数据中岛计算模式
文章浏览阅读2.1k次。AJAX 流行之后,总想好好学习一下。但是众多的框架实在难以选择。说明一下 ASP.NET AJAX 并不包括在 AJAX 框架之中。刚开始学了 JQuqery, 众多的 $get(),...等等符号早已把我搞晕了。暂时就放弃了。后来学习 ASP.NET AJAX ,在微软的领导下,逐渐由服务器端转向客户端编程。 激起我客户端编程的兴趣,才想起学习一下了 Jquery. 随着WEB2._jquery ajax asp.net 认证
文章浏览阅读1.7k次。前段时间在用google map api的函数库的时候,发现里面的downloadUrl函数非常好用,所以自己写了一个。用腻了那些什么框架什么池,到头来发现越简单的东西越是适合我这种懒人。downloadUrl(url, callback, data);参数说明: url不用说了; callback是回调函数,函数调用的时候会有两个参数:data, responseCode,data就_xmlhttprequest downloadurl
文章浏览阅读956次。前些时间写了几篇关于XMLHTTP运用的实例.(可以到http://dev.csdn.net/user/wanghr100看之前的几编关于XMLHTTP的介绍.)近来看论坛上经常有人提问关于如何无刷新,自动更新数据.传统上,我们浏览网页,如果加入最新的数据.只能是等我们重新向服务器端请求时才能显示出来.但是,对于一些时效性很强的网站.传统的这种做法是不能满足的.我们可以让程序自动刷新.定时_后端xml怎么实现数据有救新增,没有就更新
文章浏览阅读3.3k次。 XMLHttpRequest调用XMLHttpRequest Call ●●●调用,回调,下载,抓取,实时,查询,远程通信(Remoting),远程通信脚本(RemoteScripting),同步,上传,XMLHttpRequest图6-2:XMLHttpRequest调用 目标故事Reta正在一个批发商网站上购买商品。每次她添加一个商品到购物车时,web站点发出_createxmlhttpre
文章浏览阅读1.3k次。function clearitem(){ var drp1 = document.getElementById("drp1"); while(drp1.options.length>0) { drp1.options.remove(0); } }//动态更改方法(根据城市代码取得该市商业区并添加到DropDownList中_dropdownlist根據動態變化
文章浏览阅读1.9k次。因為 Json.net 是有附原始碼的,他也附了單元測試的專案,底下是我額外增加的UnitTest,我的目標就是讓底下的測試可以pass,而且原來的Test 也要都能通過。 ValueTypeTest.csusing System;using NUnit.Framework;namespace Newtonsoft.Json.Test { [TestFixture] public cl_vb 無效的 json 基本型別
文章浏览阅读844次。利用XMLHTTP无刷新获取数据. 客户端和服务器端数据的交互有几种方法.1.提交,通过提交到服务器端.也称"有刷新"吧.2.通过XMLHTTP无刷新提交到服务器端,并返回数据.也称"无刷新"吧.利用XMLHTTP我们可以实现很多很强大的应用.这文章主要介绍它的一些简单的应用.附:因为XMLHTTP是IE5.0+支持的对象.所以你必须要有IE5.0+才能看到效果.client.htm_xmlhttp取源码没有更新
文章浏览阅读1.8k次。Json.Net 無法序列基本型別(string, int),Asp.Net Ajax 無法正確序列日期,AjaxPro序列出我不想要的_type字串 1. Json.Net 是我最常使用的序列/反序列json套件,標榜速度快,對於一對多關係的object 也都能正常運作, 己能滿足我平日的需要,但前幾天突然有個情況,我要序列的是一個泛型參數,該參數不一定是物object型別,有可能是st_token string in state start
文章浏览阅读1.3k次。转载自:http://www.cnblogs.com/JeffreyZhao/archive/2007/01/31/update_the_updatepanels_by_js.html众 所周知,UpdatePanel是通过Trigger来更新的。被设定为Trigger的控件在PostBack之后会被客户端所截获,并且使用 XMLHttpRequest对象发送内容,然后服务器端由ScriptMan_web.ui.updatepanel 和 updatepanel 的区别
文章浏览阅读1.9k次。有些时候,只是需要更新页面的一个部分甚至只是更新中间的几个数据却需要从服务器DOWN整个页面,导致各种资源的浪费。使用数据岛技术可以很好的解决这个问题:通过定时器或用户事件触发数据岛(XML对象)象服务器获取数据,在数据获取完成后,适时更新相关数据。示例HTML部分:http://localhost/WebService/LoadData/FeaturedService.asmx/GetScore_web数据岛
文章浏览阅读1k次。在页面上使用ActiveXObject的代价是很大的,如果我们的无刷新页面使用xmlhttp技术,我们或许需要频繁的建立xmlhttp对象,当然 我们也可以使用全局变量来cache一个xmlhttp对象实例。但是这样的方法适合于同步方式xmlhttp通信,而对于异步方式xmlhttp通信将 会出现问题。由于没有了进程的堵塞,用户可能再次调用同一个xmlhttp实例,如果这时前一个通信未完成,那么就
文章浏览阅读998次。 by Lokesh Dhakar 译: croc查看原文概要:Lightbox JS 是一个简单而又谦恭的用来把图片覆盖在当前页面上的脚本. 它能被快速安装并且运作于所有流行的浏览器.最新更新 Version 2.0 图片集: 分组相关的图片并且能轻松的导航它们 视觉特效: 奇特的自适应调整 向后兼容: yes! 点击这里查看实例_on lightbox 2 by lokesh dhakar