JavaScript Ajax之美~

fkdt2134 8年前發布 | 14K 次閱讀 Ajax JavaScript開發

曾經有一段時期,因為開發人員對JavaScript的濫用導致其遭受了一段時間的冷門時期,不被大家看好,后來,到了2005年,Google公司的很多技術都是用了ajax之后,JavaScript才又火熱了起來,可以說,是Ajax拯救了JavaScript,就目前來說,熟練使用Ajax已經成為了所有web開發人員必須掌握的技能。那么Ajax又是什么呢? 它的作用是什么呢?

第一部分:Ajax簡介

Ajax即Asynchronous JavaScript +XML的簡寫,這一技術能夠向服務器請求額外的數據而無需卸載頁面,會帶來更好地用戶體驗。Ajax的核心是XMLHttpRequest對象(簡稱XHR,這一對象受到chrome、safari、FF、opera等主流瀏覽器的支持),這是由微軟首先引入的一個特性,IE 瀏覽器使用 ActiveXObject,后來瀏覽器提供商都提供了相同的實現。 XHR對象的存在,意味著當用戶點擊之后,不必刷新頁面也可以從后臺取得新數據,也就是說,可以試用XHR對象取得新數據,然后通過DOM方式將新數據插入到頁面中,達到對網頁的某部分進行更新的效果。 值得注意的是:雖然,Ajax中包含了xml,但是我們在無需刷新頁面就得到的數據不一定是xml數據。

第二部分:XHR對象的創建

上面講到,Ajax的核心是XMLHttpRequest對象,那么我們如何創建一個XMLHttpRequest對象呢?

首先,我們應當知道:所有瀏覽器都支持XMLHttpRequest對象,其中IE5和IE6使用ActiveXObject對象。并且現在所有瀏覽器(IE7+、FireFox、Chrome、Safari以及Opera)均內建了XMLHttpRequest對象。于是創建XMLHttpRequest對象的語法是:

var xhr = new XMLHttpRequest();

剛剛提到老版本的Internet Explorer(IE5和IE6)使用的是ActiveXObject對象,所以語法是:

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

注意:其中傳入的“Microsoft.XMLHTTP”是不能改變的。

于是,為了應對所有的現代瀏覽器(包括IE5和IE6),請首先檢查是否支持XMLHttpRequest對象:如果支持,則創建XMLHttpRequest對象;如果不支持,則創建ActiveXObject對象:

var xmlHttp=null;
if(window.XMLHttpRequest)
{   
    xmlHttp=new XMLHttpRequest();
}
else
{
    xlmHttp=new ActiveXObject("Microsoft.XMLHTTP");
}

關于這個應對所有現代瀏覽器的代碼應當注意:

  • 我將xmlHttp的值設置為null,是因為null值表示一個空對象指針,而這也正是使用typeof操作符檢測null值是會返回“object”的原因,因此:如果定義的變量準備在將來用于保存對象,那么最好將該變量初始化為null而不是其他值。
  • 之所以可以試用window.XMLHttpRequest來檢測其是否存在,是因為XMLHttpRequest是window對象的屬性。

第三部分:XHR對象的用法(屬性與方法等)

上面兩部分,我們介紹XHR對象是什么以及怎么創建,這一部分我將談一談XHR對象的用法。

⑴.open()方法

既然XHR是一個對象,那么它就一定有自己的屬性和方法。在使用XHR對象時,要調用的第一個方法是open()。它接受3個參數:

  1. 要發送的請求的類型:get、post、put、delete等等。
  2. 請求的URL(這個URL既可以是絕對路徑,也可以是相對路徑)。
  3. 是否異步發送請求的布爾值:true表示異步發送請求,false表示同步發送請求。

舉例如下:

xhr.open("get","example.php",true);

此時,這段代碼會啟動一個針對example.php的GET請求。 注意:open()方法并不會真正的發送請求而只是啟動一個請求以備發送。 那么怎么才能發送特定的請求呢,這是就要用到send()方法了。

⑵. send()方法

剛剛說到open()方法,只是開啟(open),還沒有發送,而send才是真正地發送。它接受一個參數:

  • 作為請求主體發送的數據

注意:如果不需要通過請求主體發送數據,則必須傳入null。一般get請求不需要傳入參數,而對于post請求,如果需要像 HTML 表單那樣 POST 數據,請使用 setRequestHeader() 來添加 HTTP 頭。然后在 send() 方法中規定您希望發送的數據。這一部分會詳細介紹,下面舉一個簡單例子:

xhr.open("get","example.php",true);
xhr.send(null);

(3).XHR對象的幾個屬性

通過send()發送之后,會接受到響應,響應的數據會自動填充XHR對象的屬性。主要有以下幾種:

  • responseText:作為響應主體被返回的文本
  • responseXML:如果響應的內容類型是"text/xml"或"application/xml",這個屬性中將保存包含著相應數據的XML DOM文檔。
  • status:響應的http狀態
  • statusText:Http狀態的說明

在接收到響應后,一般是先檢查status屬性,來確定響應是否成功返回,一般狀態代碼200表示成功(以2開頭即表示成功),這是responseText就可以被訪問了。 而狀態代碼為304表示請求的資源并沒有被修改,可以直接使用瀏覽器中緩存的版本, 因此這種響應也是有效的。于是可以通過下面的代碼檢測這兩種狀態:

xhr.open("get","example.php",false);
    xhr.send(null);
    if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
        alert(xhr.responseText);
    }else{
        alert("Request waw unseccessful:"+"xhr.status");
    }

XHR對象的readystate屬性

使用Ajax我們當然還是希望發送異步請求的:如果發送同步請求,那么一旦網卡住了,這個頁面就不會有任何反應而是繼續等待響應,但是發送異步請求,即使網卡住,也不用擔心,因為它是異步的。 而readystate屬性可以檢測到請求/響應過程的當前活動階段 。它有5個取值,分別如下:

關鍵: 只要readystate的值改變(比如從0變為1,從1變為2等等),那么每次地改變都會觸發readystatechange事件。并且可以通過這個時間檢測每次狀態變化后的readystate的值。 當值為4是最重要的,因為這事所有的數據已經準備就緒。看一個例子:

var xhr=new XMLHttpRequest();
    xhr.open("get","example.php",false);
    xhr.onreadystatechange=function(){
        if(readystate==4){
            if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
                alert(xhr.responseText);
            }else{
                alert("Request waw unseccessful:"+"xhr.status");
            }
        }
    };
    xhr.send(null);

注意以下幾點:

  • xhr.onreadystatechange前面有一個on,這是因為我們使用的是DOM0級方法為XHR對象添加了時間處理程序, 沒有利用addEventListener這種DOM2級方法,是因為并非所有的瀏覽器都支持DOM2級方法 。
  • 這個例子中我們沒有使用this對象,是因為onreadystatechange時間處理程序的作用域問題。 如果使用this對象,在有的瀏覽器中會導致函數執行失敗或者導致發生錯誤。 因此,使用實際的XHR對象實例便利那個是一種較為可靠的方式。

(4).abort()方法

在接受到響應之前,我們還可以使用abort()方法來取消異步請求,如下所示:

xhr.abort();

在調用了這個方法之后,XHR對象會停止觸發事件,而且也不再允許訪問任何與響應有關的對象屬性。

(5)setRequestHeader()方法、getResponseHeader()方法、getAllResponseHeader()方法在第四部分介紹完之后講解

第四部分:HTTP頭部信息

因為使用Ajax和后臺交互,那么就一定離不開http協議了。而HTTP請求和響應都會帶有相應的頭部信息。

在默認情況下,在發送XHR請求的同時,還會發送以下頭部信息。

  • Accept:瀏覽器能夠處理的內容類型
  • Accept-Charset:瀏覽器能夠顯示的字符集
  • Accept-Encodding:瀏覽器能夠處理的壓縮編碼
  • Accept-Language:瀏覽器當前設置的語言
  • Connection:瀏覽器與服務器之間鏈接的類型
  • Cookie:當前頁面設置的任何Cookie
  • Host:發出請求的頁面所在的域
  • Referer:發出請求頁面的URI
  • User-Agent:瀏覽器的用戶代理字符串   

下面這張圖片是我的chrome瀏覽器開發者工具下的network中截屏所得,大家可以對照參考:

我們還可以通過 setRequestHeader() 方法來設置自定義的請求頭部信息。這個方法接收兩個參數:頭部字段的名稱和頭部字段的值。并且我們必須在open()方法之后,在send()方法之前來調用setRequestHeader()方法。舉例如下:

var xhr=new XMLHttpRequest();
        xhr.open("get","example.php",true);
        xhr.setRequestHeader("myHeader","myValue");
        xhr.send(null);

這里只需要注意: 這里傳入的頭部字段的名稱最好是自定義的,而不要使用瀏覽器正常發送的字段名稱,否則有可能會影響瀏覽器的響應。 (因為有的瀏覽器允許開發人員重寫默認的頭部信息,而有的瀏覽器是不允許開發人員重寫默認的頭部信息的)。

除了可以為請求頭部增加自定義的頭部字段,我們還可以獲取頭部字段。我們可以調用XHR對象的getResponseHeader()方法并傳入一個頭部字段名稱,便可以獲得響應頭部信息。還可以調用XHR對象的getAllResponseHeaders()方法取得一個包含所有頭部信息的長字符串。

如下所示:

var myHeader=xhr.getResponseHeader("myHeader");
        var allHeaders=xhr.getAllResponseHeaders();

第五部分:GET請求

get請求用于向服務器查詢某些信息。 注意,查詢字符串(名稱/值對)是在 GET 請求的 URL 中發送的。  但是,有時候可能會出現問題,即查詢字符串的格式有問題。查詢字符串的每個參數的名稱和值都必須使用 encodeURIComponent() 進行編碼,然后才能放到URL的末尾;而且所有的名值對都必須用&分隔。如下所示:

xhr.open("get","example.php?name1=value1&name2=value2",true);

而下面的這個函數可以輔助向現有的URI的末尾添加查詢字符串:

function addURIParam(url,name,vaule){
            url+=(url.indexOf("?")==-1?"?":"&");
            url+=encodeURIComponent(name)+"="+encodeURIComponent(value);
            return url;
        }
        var url="example";
        url=addURIParam(url,"name","zzw");
        url=addURIParam(url,"sex","male");
        xhr.open("get",url,false);

實際上,函數中的第一句是先判斷url后面有沒有查詢字符串,如果沒有,就添加?,如果有,就添加&,因此,最終的url為"example.php?name=zzw&sex=male"。

另外,對于get請求需要注意:

  • GET請求可以被緩存
  • GET請求保留在歷史記錄中
  • GET請求可悲收藏為書簽
  • GET請求不應該在處理敏感數據時使用(因為查詢字符串是暴露的,任何人都可以看到)
  • GET請求有長度限制,超過最大長度后一般無法提交
  • GET請求只應當用于取回數據

第六部分:POST請求

POST請求的使用頻率僅次于GET請求,通常用于向服務器中發送應該被保存的數據。 請注意,查詢字符串(名稱/值對)是在 POST 請求的 HTTP 消息主體中發送的。 而GET請求卻不是這樣的。POST請求的主體可以包含很多的數據,而且格式不限。

默認情況下,服務器對post請求和提交web表單的請求不會一視同仁,因此, 我們可以試用XHR對象和模仿表單提交:首先將Content-Type頭部信息設置為application/x-www-form-urlencoded,也就模仿成了表單提交時的內容類型(贊一個!)。 接著需要在以適當的格式創建一個字符串,post數據的格式和查詢字符串格式相同,如果需要將頁面中表單的數據序列化,在通過XHR發送到服務器,那么就要使用serialize()函數來創建這個字符串。下面舉兩個例子:

xhr.open("POST","example.php",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send("fname=Bill&lname=Gates");

這里我們沒有將字符串序列化。

xhr.open("POST","example.php",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
var form=document.getElementById("user-info");
xhr.send(serialize(form));

這里我們使用serialize()函數進行了序列化。

另外,對于post請求需要注意:

  • POST請求不會被緩存
  • POST請求不會保留在瀏覽器歷史記錄中
  • POST請求不能被收藏為書簽
  • POST請求對數據長度沒有要求

講過了POST請求和GET請求,那么它們之間的區別是什么呢?

第七部分:同源策略

通過XHR實現Ajax通信的一個主要限制,來源于跨域安全策略,又稱為同源策略。那么什么使同源策略呢?

同源策略,它是由Netscape提出的一個著名的安全策略,默認情況下,XHR對象只能訪問與包含他的頁面位于同一個域中的資源,這種安全策略可以預防某些惡意行為。現在所有支持JavaScript的瀏覽器都會使用這個策略,這種安全策略可以預防某些惡意行為,比如,A網站是一家銀行,如果用戶登陸了以后,其他的網站可以讀取A網站的Cookie,那么其他網站就可以為所欲為了。但是,實現合理的跨域請求對開發某些瀏覽器的應用程序也是至關重要的。后續的文章我會介紹跨域資源共享的知識。這里僅介紹同源策略。

所謂 同源 是指: 協議、域名和端口相同

舉例說:http://www.cnblogs.com/dir/page.html這個網址。

協議:http://

域名:www.cnblogs.com

端口:80(默認端口可以省略)。

對于這個網址的同源情況如下:

  • http://www.cnblogs.com/cat/index.html (同源)
  • http://cnblogs.com/dir/page.html(不同源-域名不同)
  • https://cnblogs.com/dir/page.html(不同源-協議不同)
  • http://www.cnblogs.com:81/dir/page.html(不同源-端口不同)

 

 

來自:http://www.cnblogs.com/zhuzhenwei918/p/6083797.html

 

 本文由用戶 fkdt2134 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!