一日精通Ajax技術

來源:互聯網
上載者:User


  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 >
<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中會有問題,大家可能參考與相容性有關的文檔。



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.