1. 程式人生 > >AJAX的實現步驟(完整過程)

AJAX的實現步驟(完整過程)

AJAX全稱為“Asynchronous JavaScript and XML”(非同步JavaScript和XML),是一種建立互動式網頁應用的網頁開發技術。Ajax的工作原理相當於在使用者和伺服器之間加了—箇中間層(AJAX引擎),使使用者操作與伺服器響應非同步化。並不是所有的使用者請求都提交給伺服器,像—些資料驗證和資料處理等都交給Ajax引擎自己來做, 只有確定需要從伺服器讀取新資料時再由Ajax引擎代為向伺服器提交請求。

實現一個AJAX非同步呼叫和區域性重新整理,通常需要以下幾個步驟:

       建立XMLHttpRequest物件,也就是建立一個非同步呼叫物件.

建立一個新的HTTP請求,並指定該HTTP請求的方法、URL及驗證資訊.

       設定響應HTTP請求狀態變化的函式.

       傳送HTTP請求.

       獲取非同步呼叫返回的資料.

       使用JavaScript和DOM實現區域性重新整理.

實現步驟如下:

1、建立XMLHttpRequest物件

不同的瀏覽器使用的非同步呼叫物件也有所不同,在IE瀏覽器中非同步呼叫使用的是XMLHTTP元件中的XMLHttpRequest物件,而在Netscape、Firefox瀏覽器中則直接使用XMLHttpRequest元件。因此,在不同瀏覽器中建立XMLHttpRequest物件的方式都有所不同.

    在IE瀏覽器中建立XMLHttpRequest物件的方式如下所示:

    var xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");

    在Netscape瀏覽器中建立XMLHttpRequest物件的方式如下所示:

    var xmlHttpRequest = new XMLHttpRequest();

    由於無法確定使用者使用的是什麼瀏覽器,所以在建立XMLHttpRequest物件時,最好將以上兩種方法都加上.如以下程式碼所示:

 <script language = "javascript" type = "text/javascript">
        var xmlHttpRequest;  //定義一個變數,用於存放XMLHttpRequest物件
        function createXMLHttpRequest()    //建立XMLHttpRequest物件的方法
         {
            if(window.ActiveXObject)   //判斷是否是IE瀏覽器
             {
                xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");  //建立IE瀏覽器中的XMLHttpRequest物件
               }
               else if(window.XMLHttpRequest)    //判斷是否是Netscape等其他支援XMLHttpRequest元件的瀏覽器
               {
                xmlHttpRequest = new XMLHttpRequest();  //建立其他瀏覽器上的XMLHttpRequest物件
                }
                    }
    </script>
                         createXMLHttpRequst();   //呼叫建立物件的方法


"if(window.ActiveXObject)"用來判斷是否使用IE瀏覽器.其中ActiveXOject並不是Windows物件的標準屬性,而是IE瀏覽器中專有的屬性,可以用於判斷瀏覽器是否支援ActiveX控制元件.通常只有IE瀏覽器或以IE瀏覽器為核心的瀏覽器才能支援Active控制元件.

      "else if(window.XMLHttpRequest)"是為了防止一些瀏覽器既不支援ActiveX控制元件,也不支援XMLHttpRequest元件而進行的判斷.其中XMLHttpRequest也不是window物件的標準屬性,但可以用來判斷瀏覽器是否支援XMLHttpRequest元件.

      如果瀏覽器既不支援ActiveX控制元件,也不支援XMLHttpRequest元件,那麼就不會對xmlHttpRequest變數賦值.

2、建立HTTP請求

  建立了XMLHttpRequest物件之後,必須為XMLHttpRequest物件建立HTTP請求,用於說明XMLHttpRequest物件要從哪裡獲取資料.通常可以是網站中的資料,也可以是本地中其他檔案中的資料.

       建立HTTP請求可以使用XMLHttpRequest物件的open()方法,其語法程式碼如下所示:

       XMLHttpRequest.open(method,URL,flag,name,password)

       程式碼中的引數解釋如下所示:

       method:該引數用於指定HTTP的請求方法,一共有get、post、head、put、delete五種方法,常用的方法為get和post。

       URL:該引數用於指定HTTP請求的URL地址,可以是絕對URL,也可以是相對URL。

       flag:該引數為可選引數,引數值為布林型。該引數用於指定是否使用非同步方式。true表示非同步方式、false表示同步方式,預設為true。

       name:該引數為可選引數,用於輸入使用者名稱。如果伺服器需要驗證,則必須使用該引數。

       password:該引數為可選引數,用於輸入密碼。如果伺服器需要驗證,則必須使用該引數。通常可以使用以下程式碼來訪問一個網站檔案的內容。

       xmlHttpRequest.open("get","http://www.aspxfans.com/BookSupport/JavaScript/ajax.htm",true);

       或者使用以下程式碼來訪問一個本地檔案內容:

       xmlHttpRequest.open("get","ajax.htm",true);

注意:如果HTML檔案放在Web伺服器上,在Netscape瀏覽器中的JavaScript安全機制不允許與本機之外的主機進行通訊。也就是說,使用open()方法只能開啟與HTML檔案在同一個伺服器上的檔案。而在IE瀏覽器中則無此限制(雖然可以開啟其他伺服器上的檔案,但也會有警告提示)。

3、設定響應HTTP請求狀態變化的函式

建立完HTTP請求之後,應該就可以將HTTP請求傳送給Web伺服器了。然而,傳送HTTP請求的目的是為了接收從伺服器中返回的資料。從建立XMLHttpRequest物件開始,到傳送資料、接收資料、XMLHttpRequest物件一共會經歷以下5中狀態。

       ⑴未初始化狀態。在建立完XMLHttpRequest物件時,該物件處於未初始化狀態,此時XMLHttpRequest物件的readyState屬性值為0。

       ⑵初始化狀態。在建立完XMLHttpRequest物件後使用open()方法建立了HTTP請求時,該物件處於初始化狀態。此時XMLHttpRequest物件的readyState屬性值為1。

       ⑶傳送資料狀態。在初始化XMLHttpRequest物件後,使用send()方法傳送資料時,該物件處於傳送資料狀態,此時XMLHttpRequest物件的readyState屬性值為2。

       ⑷接收資料狀態。Web伺服器接收完資料並進行處理完畢之後,向客戶端傳送返回的結果。此時,XMLHttpRequest物件處於接收資料狀態,XMLHttpRequest物件的readyState屬性值為3。

       ⑸完成狀態。XMLHttpRequest物件接收資料完畢後,進入完成狀態,此時XMLHttpRequest物件的readyState屬性值為4。此時接收完畢後的資料存入在客戶端計算機的記憶體中,可以使用responseText屬性或responseXml屬性來獲取資料。

        只有在XMLHttpRequest物件完成了以上5個步驟之後,才可以獲取從伺服器端返回的資料。因此,如果要獲得從伺服器端返回的資料,就必須要先判斷XMLHttpRequest物件的狀態。

       XMLHttpRequest物件可以響應readystatechange事件,該事件在XMLHttpRequest物件狀態改變時(也就是readyState屬性值改變時)激發。因此,可以通過該事件呼叫一個函式,並在該函式中判斷XMLHttpRequest物件的readyState屬性值。如果readyState屬性值為4則使用responseText屬性或responseXml屬性來獲取資料。具體程式碼如下所示:

//設定當XMLHttpRequest物件狀態改變時呼叫的函式,注意函式名後面不要新增小括號
       xmlHttpRequest.onreadystatechange = getData;
       //定義函式
       function getData()
       {
              //判斷XMLHttpRequest物件的readyState屬性值是否為4,如果為4表示非同步呼叫完成
              if(xmlHttpRequest.readyState == 4)
              {
                          //設定獲取資料的語句
               }
        }

4、設定獲取伺服器返回資料的語句

如果XMLHttpRequest物件的readyState屬性值等於4,表示非同步呼叫過程完畢,就可以通過XMLHttpRequest物件的responseText屬性或responseXml屬性來獲取資料。

       但是,非同步呼叫過程完畢,並不代表非同步呼叫成功了,如果要判斷非同步呼叫是否成功,還要判斷XMLHttpRequest物件的status屬性值,只有該屬性值為200,才表示非同步呼叫成功,因此,要獲取伺服器返回資料的語句,還必須要先判斷XMLHttpRequest物件的status屬性值是否等於200,如以下程式碼所示:

 if(xmlHttpRequst.status == 200)
       {
                //使用以下語句將返回結果以字串形式輸出
                document.write(xmlHttpRequest.responseText);
                //或者使用以下語句將返回結果以XML形式輸出
                //document.write(xmlHttpRequest.responseXML);
       }
       注意:如果HTML檔案不是在Web伺服器上執行,而是在本地執行,則xmlHttpRequest.status的返回值為0。因此,如果該檔案在本地執行,則應該加上xmlHttpRequest.status == 0的判斷。
        通常將以上程式碼放在響應HTTP請求狀態變化的函式體內,如以下程式碼所示:
       //設定當XMLHttpRequest物件狀態改變時呼叫的函式,注意函式名後面不要新增小括號
       xmlHttpRequest.onreadystatechange = getData;
       //定義函式
       function getData()
       {
               //判斷XMLHttpRequest物件的readyState屬性值是否為4,如果為4表示非同步呼叫完成
                if(xmlHttpRequest.readyState==4)
                {
                       //設定獲取資料的語句 state=200說明伺服器成功響應返回的結果是正確的
                       if(xmlHttpRequest.status == 200 || xmlHttpRequest.status == 0)
                       {
                               //使用以下語句將返回結果以字串形式輸出
                               document.write(xmlHttpRequest.responseText);
                               //或者使用以下語句將返回結果以XML形式輸出
                               //docunment.write(xmlHttpRequest.responseXML);
                       }
                }
       }

5、傳送HTTP請求

在經過以上幾個步驟的設定之後,就可以將HTTP請求傳送到Web伺服器上去了。傳送HTTP請求可以使用XMLHttpRequest物件的send()方法,其語法程式碼如下所示:

       XMLHttpRequest.send(data)

       其中data是個可選引數,如果是get請求的資料寫在url中,那這裡即可以使用null來替代。如果是post請求,data引數的格式與在URL中傳遞引數的格式類似,以下程式碼為一個send()方法中的data引數的示例:

       name=myName&value=myValue

另外,get和post請求傳送請求的程式碼實現還有以下區別:

                get請求需要防止客戶端和伺服器互動過程亂編碼問題,注意在伺服器配置編碼格式或者把get請求的url用encodeURI方法處理轉換為utf-8,而post則預設是utf-8編碼,伺服器端預設是IOS-8859-1,如果也遇到亂碼問題,則在伺服器端設定如下程式碼:

                request.setCharacterEncoding("utf-8");

而且根據http協議要求post請求需要額外設定請求頭,如下:

xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")

       只有在使用send()方法之後,XMLHttpRequest物件的readyState屬性值才會開始改變,也才會激發readystatechange事件,並呼叫函式。


6、區域性更新

  在通過Ajax的非同步呼叫獲得伺服器端資料之後,可以使用JavaScript或DOM來將網頁中的資料進行區域性更新。常用的區域性更新的方式有以下3種:

       ⑴表單物件的資料更新

       表單物件的資料更新,通常只要更改表單物件的value屬性值,其語法程式碼如下所示:

        FormObject.value = "新數值"

        有關表單物件的資料更新的示例如以下程式碼所示:


<html>
                  <head>
                               <title>區域性更新</title>
                               <script language = "javascript" type = "text/javascript">
                               <!--
                                          function changeData()
                                          {
                                                    document.myForm.myText.value = "更新後的資料"
                                          }
                               -->
                  </head>
                 <body>
                            <form name = "myForm">
                                      <input type = "text" value = "原資料" name = "myText">
                                      <input type = "button" value = "更新資料" onclick = "changeData()">
                            </form>
                 </body>
        </html>

  ⑶DOM技術的區域性重新整理

       innerText和innerHTML兩個屬性都是IE瀏覽器中的屬性,在Netscape瀏覽器中並不支援該屬性。但無論是IE瀏覽器還是Netscape瀏覽器,都支援DOM。在DOM中,可以修改標籤間的文字內容。

       在DOM中,將HTML文件中的每一對開始標籤和結束標籤都看成是一個節點。例如HTML文件中有一個標籤如下所示,那麼該標籤在DOM中稱之為一個“節點”。

       <div id = "myDiv">原資料</div>

       在DOM中使用getElementById()方法可以通過id屬性值來查詢該標籤(或者說是節點),如以下語句所示:

       var node = document.getElementById("myDiv");

       注意:在一個HTML文件中,每個標籤中的id屬性值是不能重複的。因此,使用getElementById()方法獲得的節點是唯一的。

       在DOM中,認為開始標籤與結束標籤之間的文字是該節點的子節點,而firstChild屬性可以獲得一個節點下的第1個子節點。如以下程式碼可以獲得<div>節點下的第1個子節點,也就是<div>標籤與</div>標籤之間的文位元組點。

      node.firstChild

      注意,以上程式碼獲得的是文位元組點,而不是文字內容。如果要獲得節點的文字內容,則要使用節點的nodeValue屬性。通過設定nodeValue屬性值,可以改變文位元組點的文字內容。完整的程式碼如下所示:

      <html>

               <head>

                         <title>區域性更新</title>

                         <script language = "javascript" type = "text/javascript">

                         <!--

                                   function changeData()

                                   {

                                             //查詢標籤(節點)

                                             var node = document.getElementById("myDiv");

                                             //在DOM中標籤中的文字被認為是標籤中的子節點

                                             //節點的firstChild屬性為該節點下的第1個子節點

                                             //nodeValue屬性為節點的值,也就是標籤中的文字值

                                             node.firstChild.nodeValue = "更新後的資料";

                                   }

                         -->

                         </script>

               </head>

      </html>

      注意:目前主流的瀏覽器都支援DOM技術的區域性重新整理。



7、完整的AJAX例項
       <html>
                <head>
                           <title>AJAX例項</title>
                           <script language="javascript" type="text/javascript">    
                           <!--
                                     var xmlHttpRequest;  //定義一個變數用於存放XMLHttpRequest物件
                                     //定義一個用於建立XMLHttpRequest物件的函式
                                     function createXMLHttpRequest()
                                    {
                                            if(window.ActiveXObject)
                                            {
                                                   //IE瀏覽器的建立方式
                                                   xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
                                            }else if(windew.XMLHttpRequest)
                                           {
                                                  //Netscape瀏覽器中的建立方式
                                                  xmlHttpRequest = new XMLHttpRequest();
                                            }
                                   }
                                   //響應HTTP請求狀態變化的函式
                                   function httpStateChange()
                                   {
                                          //判斷非同步呼叫是否完成
                                         if(xmlHttpRequest.readyState == 4)
                                        {
                                                //判斷非同步呼叫是否成功,如果成功開始區域性更新資料
                                                if(xmlHttpRequest.status == 200||xmlHttpRequest.status == 0)
                                                {
                                                       //查詢節點
                                                       var node = document.getElementById("myDIv");
                                                        //更新資料
                                                        node.firstChild.nodeValue = xmlHttpRequest .responseText;
                                                }
                                                else
                                               {
                                                     //如果非同步呼叫未成功,彈出警告框,並顯示出錯資訊
                                                     alert("非同步調用出錯/n返回的HTTP狀態碼為:"+xmlHttpRequest.status + "/n返回的HTTP狀態資訊為:" + xmlHttpRequest.statusText);
                                               }
                                         }
                                     }
                                    //非同步呼叫伺服器段資料
                                   function getData(name,value)
                                  {                   
                                       //建立XMLHttpRequest物件
                                       createXMLHttpRequest();
                                       if(xmlHttpRequest!=null)
                                       {
                                            //建立HTTP請求
                                            xmlHttpRequest.open("get","ajax.text",true)
                                           //設定HTTP請求狀態變化的函式
                                            xmlHttpRequest.onreadystatechange = httpStateChange;
                                           //傳送請求
                                          xmlHttpRequest.send(null);
                                        }
                                  }
                           -->
                          </script>
                </head>
                <body>
                         <div id="myDiv">原資料</div>
                         <input type = "button" value = "更新資料" onclick = "getData()">
                </body>
       </html>