当前位置: 首页 > 图文教程 > XML家族 > XML > 一日精通Ajax技术

XML
XML简易教程之四
XML与HTML的结合(上)
XML与HTML的结合(下)
XML入门的常见问题(一)
XML入门的常见问题(二)
XMLHTTP资料
什么是XML
什么是 XML Web Service
XML正在接管Web服务 成为SOA的基础
怎么样在网页上读取远程xml的数据
XML教程—编写结构完整的XML文档
读写xml文件的2个小函数
XML文档的基本操作
初学者如何开发出一个高质量的J2EE系统
优化 JavaScript 代码
自动更新程序的设计框架
使Firefox对XML的处理兼容IE的节点处理方法
WML学习之四 锚和任务
WML学习之五 显示表单
WML学习之六 事件

XML 中的 一日精通Ajax技术


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-17   浏览: 37 ::
收藏到网摘: n/a

 


  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中会有问题,大家可能参考与兼容性有关的文档。