js-ajax詳解

淺淺一諾發表於2018-12-19

ajax

  1. 建立ajax

function createXHR(){
    if(typeOf XMLHttpRequest != 'undefined'){
        return new XMLHttpRequest();
    }else if(typeOf ActiveXObject != 'undefined'){
        if(typeOf arguments.callee.activeXString != 'string'){
                let version = ['MSXML2.XMLHttp.6.0','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp'];                for(i=0;i<version.length;i++){
                    try {
                        new ActiveXObject(version[i]);
                        arguments.callee.activeXString = version[i];
                        break;
                    } catch(ex) {
                        //跳過
                    };
                };
複製程式碼
        };
    }else{
        throw new Error('No XHR object available.');
    };
};

let xhr = new createXHR();複製程式碼

2.呼叫open();

  • 三個引數:要傳送的請求的型別('get','post'等);請求的URL;是否非同步傳送請求的布林值;
  • 呼叫:xhr.open('get','example.php',true);
  • 說明兩點:一是URL相對於執行程式碼的當前頁面(也可以是絕對路徑);二是呼叫open()方法並不會真正傳送請求,而是啟動一個請求以備傳送。
  • 注意:同源策略(同域名,同協議,同埠);

3.呼叫send();

  • 一個引數:作為請求主體傳送的資料,如果不需要必須傳null.
  • 呼叫send()後,請求就會被分派到伺服器。

4.監聽readystatechange事件,獲取xhr的readyState和status屬性值

  • 同步請求判斷xhr的status屬性就可以,非同步請求既需要獲取xhr的readyState屬性又要獲取xhr的status屬性
  • readyState

   1)該屬性表示請求/響應的當前活動階段

   2)屬性值

  • 0:未初始化。尚未呼叫open()方法;
  • 1:啟動。已經呼叫open()方法,但尚未呼叫send()方法;
  • 2:傳送。已經呼叫send()方法,但尚未收到響應;
  • 3:接收。已經收到部分響應資料;
  • 4:完成。已經收到全部響應資料,而且已經可以在客戶端使用了。   
  • status

   1)該屬性表示:響應的HTTP狀態

    2)成功返回(200<=status<300和304)

  • xhr響應返回填充的屬性

   1)responseText:作為響應主體被返回的文字

    2)responseXML:如果響應的內容型別是'text/xml'或'application/xml',這個屬性中將儲存著包含著響應資料的XML DOM文件。

    3)statusText:HTTP狀態的說明

let xhr = new createXHR();

xhr.onreadystatechange = function(){
    if(xhr.readyState==4){
        if((xhr.status>=200 && xhr.status<300) || xhr.status == 304){
            alert(xhr.responseText);
        };
    };
};

xhr.open('get','example.text',true);

xhr.send(null)複製程式碼

5.abort()方法

  • 呼叫這個方法後,XHR物件會停止觸發事件,而且也不允許訪問任何與響應有關的物件屬性

6.setRequestHeader()

  • 接收兩個引數:頭部欄位的名稱和頭部欄位的值。必須在open()方法之後和send()方法之前呼叫setRequestHeader方法

備註:

1.get請求

  • 適用:用於向伺服器查詢某些資訊。
  • 可以將查詢字串引數追加到URL的末尾,但是要正確編碼。新增引數函式:

function addURLParam(url,name,value){
    url += (url.indexOf('?')==-1?'?':'&');
    url += encodeURIComponent(name) + '=' + encodeURIComponent(value);
    return url; 
};複製程式碼

2.post請求

  • 適用:通常用於向伺服器傳送應該被儲存的資料。

3.get和post的優缺點:

  • 資源:psot消耗的資源更多
  • 速度:傳送的資料相同,get的速度最多是post的兩倍


解決跨域的方法:(參考https://www.cnblogs.com/sdcs/p/8484905.html)

  1. 通過jsonP跨域
  • 原理:通過script標籤來引入一個js檔案,這個js檔案載入成功後會執行我們在url引數中指定的函式,並且把我們需要的json資料作為引數傳入。但是jsonp這種方式是需要服務端對應頁面進行相應配合的。

2.通過修改document.domain來跨子域

  • 適用:瀏覽器中不同域的框架之間是不能進行js互動的
  • 例如:www.example.com/a.htmlexample.com/b.html這兩個頁面的document.domain都設成相同的域名就可以了。但要注意的是,document.domain的設定是有限制的,我們只能把document.domain設定成自身或更高一級的父域,且主域必須相同。例如:a.b.example.com 中某個文件的document.domain 可以設成a.b.example.com、b.example.com 、example.com中的任意一個,但是不可以設成 c.a.b.example.com,因為這是當前域的子域,也不可以設成baidu.com,因為主域已經不相同了。
  • 注意:修改document.domain的方法只適用於不同子域的框架間的互動。如果你想通過ajax的方法去與不同子域的頁面互動,除了使用jsonp的方法外,還可以用一個隱藏的iframe來做一個代理。原理就是讓這個iframe載入一個與你想要通過ajax獲取資料的目標頁面處在相同的域的頁面,所以這個iframe中的頁面是可以正常使用ajax去獲取你要的資料的,然後就是通過我們剛剛講得修改document.domain的方法,讓我們能通過js完全控制這個iframe,這樣我們就可以讓iframe去傳送ajax請求,然後收到的資料我們也可以獲得了。

3.使用window.name來進行跨域

  • window物件有個name屬性,該屬性有個特徵:即在一個視窗(window)的生命週期內,視窗載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的許可權,window.name是持久存在一個視窗載入過的所有頁面中的,並不會因新頁面的載入而進行重置。
  • 注意:window.name的值只能是字串的形式,這個字串的大小最大能允許2M左右甚至更大的一個容量,具體取決於不同的瀏覽器,但一般是夠用了。
  • 原理:在a.html頁面中使用一個隱藏的iframe來充當一箇中間人角色,由iframe去獲取data.html的資料,然後a.html再去得到iframe獲取到的資料。

    js-ajax詳解

4.通過HTML5中新引入的window.postMessage()方法來跨域傳送資料。

  • 原理:window.postMessage(message,targetOrigin) 方法是html5新引進的特性,可以使用它來向其它的window物件傳送訊息,無論這個window物件是屬於同源或不同源,目前IE8+、FireFox、Chrome、Opera等瀏覽器都已經支援window.postMessage方法。
  • 引數:第一個引數message為要傳送的訊息,型別只能為字串;第二個引數targetOrigin用來限定接收訊息的那個window物件所在的域,如果不想限定域,可以使用萬用字元 * 。
  • 接收:要接收訊息的window物件,可是通過監聽自身的message事件來獲取傳過來的訊息,訊息內容儲存在該事件物件的data屬性中。
  • 適用:一個頁面有幾個框架的那種情況,因為每一個框架都有一個window物件。在討論第二種方法的時候,我們說過,不同域的框架間是可以獲取到對方的window物件的,而且也可以使用window.postMessage這個方法
js-ajax詳解