AJAX的實現原理以及封裝
作為一名擼啊擼玩家,Ajax的中文名,讓我不禁想起了當年在S3賽季威風凜凜的武器大師,賈克斯!
難得這份熟悉感,學好AJAX(阿賈克斯),應該不是難事。
下面言歸正傳: 那何為AJAX?
首先我們從名字入手,
AJAX = Asynchronous JavaScript and XML(非同步的 JavaScript 和 XML)。
非同步,JS,XML,這幾個詞我們都認識,又或者聽說過,這樣一來,我們是不是可以大膽地能推測出AJAX並非一種新的程式語言?
沒錯,騷年,正是如此!
這只不過是新罐子裝舊藥,一種使用現有標準的新方法。而它的作用,是在不重新載入整個頁面的情況下,能夠與伺服器交換資料並更新部分網頁。
用W3School裡面的話來說,這是一種藝術。
好比git提交東西時,沒有提示便是最好的提示,這更是一種哲理思想。
滿分!
其實AJAX內部實現並不麻煩,主要通過一個叫XMLHttpRequest的物件,而這個物件在現有的瀏覽器均被支援。
可以說,它是整個AJAX實現的基礎,是瀏覽器用於後臺與伺服器交換資料的物件,有了它,才有了AJAX,也便有了部分頁面重新整理的藝術!
建立 XMLHttpRequest 物件的語法很簡單,如下:
var xhr=new XMLHttpRequest();
有了這個物件,我們就能使用其自身攜帶的方法,來做到與伺服器互動資料。
傳送請求的方法必不可少:send();
但在傳送之前,是不是得規定一下請求裡面的東西, 於是有了open();方法。
兩語法如下:
xhr.open("GET","test1.txt",true);
xhr.send();
這是具體的引數描述:
open(method ,url,async):規定請求的型別、URL 以及是否非同步處理請求。
method:請求的型別;GET 或 POST
url:檔案在伺服器上的位置
async:true(非同步)或 false(同步)
send(string): 將請求傳送到伺服器。
string:僅用於 POST 請求
至於GET與POST,該如何選擇?下面引用W3School 的一段話:
與 POST 相比,GET 更簡單也更快,並且在大部分情況下都能用。
然而,在以下情況中,請使用 POST 請求:
無法使用快取檔案(更新伺服器上的檔案或資料庫)
向伺服器傳送大量資料(POST 沒有資料量限制)
傳送包含未知字元的使用者輸入時,POST 比 GET 更穩定也更可靠
GET與POST請求本身也是一個不小的知識點,請自行學習,起碼得了解,GET請求,引數是拼接到url上面;而POST請求需要設定請求頭,用來傳遞引數,不然下面的封裝,會有點煩躁。
傳送請求就緒,接下來是響應。當請求被髮送到伺服器時,我們需要執行一些基於響應的任務。
在客戶端能做的事情不多,無非就是看一下自己的請求狀態,再監聽一下伺服器響應回來的東西,從而進行判斷,做出處理。
請求狀態如何,可以通過XMLHttpReques物件的readyState屬性的值來檢視,分為:
0: 請求未初始化
1: 伺服器連線已建立
2: 請求已接收
3: 請求處理中
4: 請求已完成,且響應已就緒
那這請求狀態值有什麼用呢?
它是以其中一個判斷條件的作用存在,只有當狀態值為4時,才證明響應的資料被解析完成,返回給客戶端。
而每當 readyState狀態值被改變時,就會觸發一個叫 onreadystatechange 事件,這個事件是XMLHttpRequest物件的一個屬性。
onreadystatechange 事件一共會被觸發 5 次(0 - 4),對應著 readyState 的每個變化。
所以說,只要當狀態值為4時,我們就可以獲得響應回來的資料。
但是剛才說了,狀態值只是作為其中的一個判斷條件,還有一個判斷條件是監聽伺服器的狀態碼。
status
200: 表示"OK"
404: 表示未找到頁面
這個狀態碼是在伺服器連線建立的時候就能監聽到(readyState狀態值為1的時候)。具體的工作流程,請下面的圖示:
到這一步,readyState為4 且status為200時,我們已經進入到拿資料的環節。
至於怎麼拿資料?更簡單,通過XMLHttpRequest的兩個屬性。
responseText :獲得字串形式的響應資料。
responseXML:獲得 XML 形式的響應資料。
輾輾轉轉,終於到了封裝的重頭戲。這次不廢話,直接上程式碼,原理都在上面了,註釋會簡單備註一下。
var $={
/*傳遞引數物件,返回拼接之後的字串*/
/*{‘name’:’jack,’age’:20}=> name=jack&age=20&*/
getParmeter:function(data){
var result="";
for(var key in data){
result=result+key+"="+data[key]+"&";
}
/*將結果最後多餘的&擷取掉*/
return result.slice(0,-1);
},
/*實現ajax請求*/
ajax:function(obj){
/*1.判斷有沒有傳遞引數,同時引數是否是一個物件*/
if(obj==null || typeof obj!="object"){
return false;
}
/*2.獲取請求型別,如果沒有傳遞請求方式,那麼預設為get*/
var type=obj.type || 'get';
/*3.獲取請求的url location.pathname:就是指當前請求發起的路徑*/
var url=obj.url || location.pathname;
/*4.獲取請求傳遞的引數*/
var data=obj.data || {};
/*4.1獲取拼接之後的引數*/
data=this.getParmeter(data);
/*5.獲取請求傳遞的回撥函式*/
var success=obj.success || function(){};
/*6:開始發起非同步請求*/
/*6.1:建立非同步物件*/
var xhr=new XMLHttpRequest();
/*6.2:設定請求行,判斷請求型別,以此決定是否需要拼接引數到url*/
if(type=='get'){
url=url+"?"+data;
/*重置引數,為post請求簡化處理*/
data=null;
}
xhr.open(type,url);
/*6.2:設定請求頭:判斷請求方式,如果是post則進行設定*/
if(type=="post"){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
/*6.3:設定請求體,post請求則需要傳遞引數*/
xhr.send(data);
/*7.處理響應*/
xhr.onreadystatechange=function(){
/*8.判斷響應是否成功*/
if(xhr.status==200 && xhr.readyState==4){
/*客戶端可用的響應結果*/
var result=null;
/*9.獲取響應頭Content-Type ---型別是字串*/
var grc=xhr.getResponseHeader("Content-Type");
/*10.根據Content-Type型別來判斷如何進行解析*/
if(grc.indexOf("json") != -1){
/*轉換為js物件*/
result=JSON.parse(xhr.responseText);
}
else if(grc.indexOf("xml") != -1){
result=xhr.responseXML;
}
else{
result=xhr.responseText;
}
/*11.拿到資料,呼叫客戶端傳遞過來的回撥函式*/
success(result);
}
}
}
};
呼叫方式與jquery類似的:
$.ajax({
url:'',
type:'',
data: {},
success:function(result){
//code...
}
});
若是有誤人子弟的地方,務必指出,大謝大謝。
——龍貓村莊1號村民敬上!