| Ajax这个名称怎么来的,本人也不得而之了,大概是(Active Javascript Action Xml)吧,说白一点就是运用了 javascript、xmlhttp和xmldom技术及网站后台来处理用户的一些操作的方法吧。
那么本人就分三步来说明如何使用 Ajax 技术来做开发。
一、用 javascript 操作 xmlhttp 对象
二、服务器部对xmlhttp请求的响应(PHP范例)
三、xmldom 的使用方法
先说第一部份:
一、用 javascript 操作 xmlhttp 对象
IE7, Mozilla ,Firefox等浏览器中,javascript是内置有 XMLHttpRequest 这个对象的,但IE5+则没有,需要用如下方法来启动: //IE 6 try{ xhttp = new ActiveXObject("Msxml2.XMLHTTP";} catch(e){ ; } //IE5+ if(xhttp == null) try { xhttp = new ActiveXObject("Microsoft.XMLHTTP";} catch(e){ ; }
那考虑不同浏览器的兼容,启动一个xmlhttp一般都要按如下方式:
CODE:[Copy to clipboard]var xhttp = null;
if(window.XMLHttpRequest){ //IE7, Mozilla ,Firefox 等浏览器内置该对象
xhttp = new XMLHttpRequest(); }else if(window.ActiveXObject){ //IE6、IE5
try{ xhttp = new ActiveXObject("Msxml2.XMLHTTP");} catch (e){ ; } if( xhttp == null) try { xhttp = new ActiveXObject("Microsoft.XMLHTTP");} catch (e){; } }
对于 xmlhttp 的使用,一般遵守如下的顺序:
1、初始化 xmlhttp 对象(上文);
2、打开链接
方法
xhttp.open("GET", purl, true);
参数一:用 GET 或 POST 方式发送数据
参数二、请求网址(只能请求你服务器上的资源,一般浏览器安全限制不能读取跨域的数据)
参数三、true 表示异步传输(服务器返回信息完成前,你可以进行其它操作),false 表示阻断方式的传输。
3、设定要发送的 http 请求头
方法:
xhttp.setRequestHeader(key,value);
一般来说,默认要发送的头是:xhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded";
这种表示发送的内容类型的请求头用于发送文本数据,而且javascript默认是以unicode发送的,还有另外一种形式是:xhttp.setRequestHeader("Content-Type","multipart/form-data";这表示发送二制形式的数据,由于安全性原因,javascript一般不能用这种方式来发送数据,所以这个头一般没什么用。
如果你的网站开启了使用 refer 参数来防盗链,那么你必须用这个方法指定 Refer 参数,或者如果用户需要登录才能进行某操作,那么要指定 Cookie 的请求头。
4、send 数据
方法:xhttp.send(postdata);
对于用 get攻手请求,不需要指定postdata,直接用 test.php?a=a&b=b 这样形式的网址来请求即可。
如果是post方式,需要用 key1=value2&key2=value2 这样的形式来对数据进行处理,把它合并在 postdata 字串中,然后发送。
注意事项:
javascript默认发送数据的方式是unicode,处理返回的数据必须是utf-8格式,因此,在发送的时候,需要用escape()函数来处理postdata和网址的value,在服务器上必须还原这些value,并把unicode转为页面编码值,因此如果用 jsp 或 asp.net 都会比较简单,但如果用php处理起来是什么费劲的,等下会教你如何做。
5、确认服务器返回资料完成下载
[1] 如果用阻断的方式来发送请求,那么直接用 if(xhttp.readyState == 4)就能判断是否完成。
readyState 的具体属性值为: 0 没open 1 没send 2 状态未知 3 正在传送 4 传送完成
当然为了保障起见,还需要加多一重判断,就是 if(xhttp.status == 200) ,status 就是 http 协议里的返回头代码
1xx 表示(唉呀,忘记了) 2xx 表示成功的信息 3xx 表示页面转移 4xx 页面不存在 5xx 表示服务器的各种错误
如果你的页面没特殊处理,一般用 if(xhttp.status == 200) 来确信内容返回是正确的
[2] 如果用异步传输,需要用 onreadystatechange 的事件来监听
xhttp.onreadystatechange = function() { //这里来进行上面阻断方式的判断 if(myajax.xhttp.readyState == 4){ if(myajax.xhttp.status == 200){ //要进行的后续操作 } } }
6、获取返回结果
属性: [1]xhttp.responseBody; [2]xhttp.responseStream; [3]xhttp.responseXml; [4]xhttp.responseText;
其中1、2都是二进制的方式,一般很少会用到,4不用看都知道了
如果服务端无意外的话[3]返回的是一个xmldom的对象
二、服务器部对xmlhttp请求的响应(PHP范例)
为了简化操作,在这里把 xmlhttp的各作操作封装为一个类
CODE:[Copy to clipboard]function DedeAjax(WiteOKFunc){ //WiteOKFunc 为异步状态事件处理函数
//xmlhttp和xmldom对象 this.xhttp = null; this.xdom = null;
//post或get发送数据的键值对 this.keys = Array(); this.values = Array(); this.keyCount = -1;
//http请求头 this.rkeys = Array(); this.rvalues = Array(); this.rkeyCount = -1; //请求头类型 this.rtype = 'text';
//初始化xmlhttp if(window.XMLHttpRequest){//IE7, Mozilla ,Firefox 等浏览器内置该对象 this.xhttp = new XMLHttpRequest(); }else if(window.ActiveXObject){//IE6、IE5 try { this.xhttp = new ActiveXObject("Msxml2.XMLHTTP");} catch (e) { } if (this.xhttp == null) try { this.xhttp = new ActiveXObject("Microsoft.XMLHTTP");} catch (e) { } } this.xhttp.onreadystatechange = WiteOKFunc; //rs: responseBody、responseStream、responseXml、responseText
//以下为成员函数 //--------------------------------
//初始化xmldom this.InitXDom = function(){ var obj = null; if (typeof(DOMParser) != "undefined") { // Gecko、Mozilla、Firefox var parser = new DOMParser(); obj = parser.parseFromString(xmlText, "text/xml"); } else { // IE try { obj = new ActiveXObject("MSXML2.DOMDocument");} catch (e) { } if (obj == null) try { obj = new ActiveXObject("Microsoft.XMLDOM"); } catch (e) { } } this.xdom = obj; };
//增加一个POST或GET键值对 this.AddKey = function(skey,svalue){ this.keyCount++; this.keys[this.keyCount] = skey; this.values[this.keyCount] = escape(svalue); };
//增加一个Http请求头键值对 this.AddHead = function(skey,svalue){ this.rkeyCount++; this.rkeys[this.rkeyCount] = skey; this.rvalues[this.rkeyCount] = svalue; };
//清除当前对象的哈希表参数 this.ClearSet = function(){ this.keyCount = -1; this.keys = Array(); this.values = Array(); this.rkeyCount = -1; this.rkeys = Array(); this.rvalues = Array(); };
//发送http请求头 this.SendHead = function(){ if(this.rkeyCount!=-1){ //发送用户自行设定的请求头 for(;i<=this.rkeyCount;i++){ this.xhttp.setRequestHeader(this.rkeys[i],this.rvalues[i]); } } if(this.rtype=='binary'){ this.xhttp.setRequestHeader("Content-Type","multipart/form-data"); }else{ this.xhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); } };
//用Post方式发送数据 this.SendPost = function(purl){ var pdata = ""; var i=0; this.state = 0; this.xhttp.open("POST", purl, true); this.SendHead(); if(this.keyCount!=-1){ //post数据 for(;i<=this.keyCount;i++){ if(pdata=="") pdata = this.keys[i]+'='+this.values[i]; else pdata += "&"+this.keys[i]+'='+this.values[i]; } } this.xhttp.send(pdata); };
//用GET方式发送数据 this.SendGet = function(purl){ var gkey = ""; var i=0; this.state = 0; if(this.keyCount!=-1){ //get参数 for(;i<=this.keyCount;i++){ if(gkey=="") gkey = this.keys[i]+'='+this.values[i]; else gkey += "&"+this.keys[i]+'='+this.values[i]; } if(purl.indexOf('?')==-1) purl = purl + '?' + gkey; else purl = purl + '&' + gkey; } this.xhttp.open("GET", purl, true); this.SendHead(); this.xhttp.send(); };
} // End Class DedeAjax 上面代码保存为: dedeajax.js
ok 那现在做个最简单的测试吧 test.htm
CODE:[Copy to clipboard]<script language='javascript' src='dedeajax.js'></script> <script language='javascript'> function WiteOK() { var myinfo = document.getElementById("myinfo"); if(myajax.xhttp.readyState == 4){ if(myajax.xhttp.status == 200){ myinfo.innerHTML = myajax.xhttp.responseText; } } } var myajax = new DedeAjax(WiteOK); myajax.AddKey("key1","----------------------------"); myajax.SendPost("test.php");
</script>
<div id='myinfo'><div> test.php
CODE:[Copy to clipboard]<? header("Content-Type: text/html; charset=gb2312"); echo $_POST['key1']; ?> 看到了什么了呢?不用激动,真正让你头痛的东西还没有出来。
把类里面的
CODE:[Copy to clipboard]this.AddKey = function(skey,svalue){ this.keyCount++; this.keys[this.keyCount] = skey; this.values[this.keyCount] = svalue;//escape(svalue); }; escape 屏蔽掉
发送 myajax.AddKey("key1","-----中---国----人-----";
看到什么了,乱码是吧?呵呵,这回开始头大了
先把 escape放回去 this.values[this.keyCount] = escape(svalue);
那么看到的就是 -----%u4E2D---%u56FD----%u4EBA-----
如何把 %u4E2D 这些东西弄回来呢?对于php而言这是一个很复杂的问题,如果用asp就简单多了
下面是我写的一个函数:
CODE:[Copy to clipboard]//unicode url编码转gbk编码函数 function Unicode2Gbk($str) { //载入对照词典 if(!isset($GLOBALS['GbkUniDic'])) { $ds = file("./data/gbk_unicode.dic"); foreach($ds as $l){ $GLOBALS['GbkUniDic'][hexdec('0x'.substr($l,0,4))] = substr($l,5,4); } } //处理字符串 $glen = strlen($str); $okstr = ""; for($i=0; $i < $glen; $i++) { if( $glen-$i > 4){ if($str[$i]=='%' && $str[$i+1]=='u'){ $uni = hexdec('0x'.substr($str,$i+2,4)); if(isset($GLOBALS['GbkUniDic'][$uni])){ $uni = $GLOBALS['GbkUniDic'][$uni]; $okstr .= chr(hexdec(substr($uni,0,2))).chr(hexdec(substr($uni,2,2))); } else $okstr .= "&#{".hexdec("0x".$uni).";"; $i = $i+5; } else $okstr .= $str[$i]; } else $okstr .= $str[$i]; } return $okstr; } 词典文件: http://www.ce86.com/myimg/data.rar
把test.php 输出改为
echo Unicode2Gbk($_POST['key1']);
正常了吧
以下说下面和xml有关的东西的了
三、xmldom 的使用方法 由于本文仅是牵针引线的作用,这一章就简单些,因为针对的是 php ,如果针对的是 asp.net 或 jsp 写涉及 web server 类的通信,已经不单纯是 ajax 的问题了,本章的任务是把test2.php
CODE:[Copy to clipboard]<? header("Content-Type: text/xml; charset=gb2312"); echo '<'.'?'."xml version=\"1.0\" encoding=\"gb2312\" ".'?'."> <myhome> <item sex=\"男\">我是小一</item> <item sex=\"女\">我是小二</item> </myhome> "; ?>这个xml文档在客户端用自己的方式展现出来。因为xml这种东西比较麻烦,所以语法也必须严格,test2.htm的页面的源码为
CODE:[Copy to clipboard]<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>ajax测试</title> </head> <body onload="WiteLoadDocument()"> <script language='javascript' src='dedeajax.js'></script> <script language='javascript'> var myajax = new DedeAjax(WiteOK); function WiteOK() { var myinfo = document.getElementById("myinfo"); var mydom = null; myinfo.innerHTML = "以下是处理结果:<br/>"; if(myajax.xhttp.readyState == 4){ mydom = myajax.xhttp.responseXml; alert(mydom); } } function WiteLoadDocument() { myajax.SendGet("test2.php"); } </script> <div id='myinfo'><div> </body> </html> 在IE中测试一下,如果弹出的对话框是 [object] 就表示成功获得返回的xml的xmldoc了。
那下面是处理:
CODE:[Copy to clipboard]function WiteOK() { var myinfo = document.getElementById("myinfo"); var mydom = null; myinfo.innerHTML = "以下是处理结果:<br/>"; if(myajax.xhttp.readyState == 4){ mydom = myajax.xhttp.responseXml; var nodeList = mydom.selectNodes("/myhome/item"); var mynode = null; var myatt = null; var mysex = ""; for(i=1;i<=nodeList.length;i++) { mynode = nodeList[i-1]; for(j=0;j < myinfo.attributes.length;j++) { if(!mynode.attributes[j]) break; myatt = mynode.attributes[j]; if(myatt.name=='sex') mysex = myatt.value; } myinfo.innerHTML += "我是:"+mynode.text+",我的性别是:"+ mysex +"<br/>"; } } }
结果:
CODE:[Copy to clipboard]以下是处理结果: 我是:我是小一,我的性别是:男 我是:我是小二,我的性别是:女 OK,目的已经达到
关于dom的部份只在IE6中测试过,可能在firefox中会有问题,大家可能参考与兼容性有关的文档。 |