我們?cè)趯W(xué)習(xí)一個(gè)東西的時(shí)候首先要知道,學(xué)習(xí)的東西是什么,他可以干什么,為什么使用它?
那么到底什么是ajax呢?
AJAX 不是 JavaScript 的規(guī)范,他是一個(gè)老伙計(jì)自創(chuàng)的名字 : Asynchronous JavaScript and XML,意思就是用JavaScript執(zhí)行異步網(wǎng)絡(luò)請(qǐng)求。
他可以干什么呢?
在整個(gè)網(wǎng)頁不重新加載的情況下,更新部分頁面的內(nèi)容。
為什么要使用它呢?
根據(jù)業(yè)務(wù)需求,發(fā)送http請(qǐng)求,拿到服務(wù)端數(shù)據(jù),在頁面上渲染數(shù)據(jù)。
好,言歸正傳,讓我們開始學(xué)習(xí)AJAX
什么是xhr
ajax技術(shù)的核心就在于 XMLHttpRequest 對(duì)象(簡稱xhr),首先由微軟引用,隨后,其他瀏覽器也支持啦該對(duì)象, xhr為向服務(wù)器發(fā)送請(qǐng)求和解析服務(wù)器響應(yīng)提供啦流暢的接口。
IE5中xhr對(duì)象,是通過ActiveX對(duì)象實(shí)現(xiàn)的,IE7+即其他瀏覽器都支持xhr對(duì)象,所以需要寫一個(gè)兼容
// 創(chuàng)建一個(gè)xhr對(duì)象(帶兼容處理)
function create(){
var xhr = null;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP')
}
return xhr;
}
注意,如果需要多個(gè)請(qǐng)求,就創(chuàng)建多個(gè)xhr對(duì)象,當(dāng)然也可以使用同一個(gè)xhr對(duì)象,但是這回終止xhr對(duì)象之前的異步請(qǐng)求
xhr對(duì)象的方法
open()
在使用xhr對(duì)象,第一個(gè)要調(diào)的方法是open(method,ull,async)
該方法是向服務(wù)器發(fā)送之前做一些設(shè)置,比如你打電話,輸入電話號(hào),然后看看是用卡一還是卡二,
xhr.open('GET','http://www.example.com/api',true)
/*
第一個(gè)參數(shù)表示使用哪種http請(qǐng)求方法,不區(qū)分大小寫,一般還是寫大寫的,常用的兩個(gè)方法:get()、post()
get方法用于常規(guī)請(qǐng)求,一般從服務(wù)器讀取數(shù)據(jù)使用該方法
post方法常用語HTML表單請(qǐng)求,一般向服務(wù)器發(fā)送數(shù)據(jù)使用該方法
第二個(gè)參數(shù)表示url,要請(qǐng)求的資源地址
第三個(gè)參數(shù)表示是否異步,true\false
/*
send()
send方法接受一個(gè)參數(shù),即要作為請(qǐng)求主體發(fā)送的數(shù)據(jù),調(diào)用send的方法,請(qǐng)求發(fā)送到服務(wù)器,該方法等于按下?lián)艽虬粹o
如果是GET方法,send()無參數(shù)或?yàn)閚ull;如果是POST方法參數(shù)是要發(fā)送的數(shù)據(jù)
xhr.send('a=1&b=2');
xhr對(duì)象的事件
xhr.onerror
xhr.onerror = function(e){
console.log(e)
}
// 該事件當(dāng)請(qǐng)求失敗時(shí)觸發(fā)
xhr.ontimeout
xhr.timeout = 1000; // 設(shè)置請(qǐng)求時(shí)間的限制,毫秒為單位,默認(rèn)為0,
xhr.ontimeout = function(){
alert('請(qǐng)求超時(shí)')
}
// 當(dāng)請(qǐng)求超過指定的時(shí)間時(shí)觸發(fā)
xhr.onprogress
// 監(jiān)聽進(jìn)度事件,如果請(qǐng)求的資源很小,直接就100%
xhr.onprogress = function(e){
console.log((e.loaded / e.total) * 100 + '%');
}
接收響應(yīng)
先檢測(cè)XHR對(duì)象的readyState屬性,該屬性表示請(qǐng)求/響應(yīng)過程的當(dāng)前活動(dòng)階段。這個(gè)屬性可取的值如下:
0(UNSENT):未初始化。尚未調(diào)用open()方法
1(OPENED):啟動(dòng)。已經(jīng)調(diào)用open()方法,但尚未調(diào)用send()方法
2(HEADERS_RECEIVED):發(fā)送。己經(jīng)調(diào)用send()方法,且接收到頭信息
3(LOADING):接收。已經(jīng)接收到部分響應(yīng)主體信息
4(DONE):完成。已經(jīng)接收到全部響應(yīng)數(shù)據(jù),而且已經(jīng)可以在客戶端使用了
在XHR對(duì)象的 readyState 屬性改變的話會(huì)觸發(fā)XHR對(duì)象的 onreadystatechange 事件,所以我們通常使用onreadystatechange事件監(jiān)聽狀態(tài)的變化
注意:一定要在open之前設(shè)置 onreadystatechange 事件,才能確保跨瀏覽器兼容性,否則將無法接收readyState屬性為0和1的情況
xhr.onreadystatecahnge = function (){
if(xhr.readyState){
// another code
}
}
單單上邊的處理還是不夠的,因?yàn)閤hr.readyState是指運(yùn)行ajax所經(jīng)歷的幾種狀態(tài),所以還需要判斷ajax是否請(qǐng)求成功
一個(gè)完整的HTTP響應(yīng)由狀態(tài)碼、響應(yīng)頭集合和響應(yīng)主體組成。在收到響應(yīng)后,這些都可以通過XHR對(duì)象的屬性和方法使用,主要有以下4個(gè)屬性
responseText: 作為響應(yīng)主體被返回的文本(文本形式)
responseXML: 如果響應(yīng)的內(nèi)容類型是'text/xml'或'application/xml',這個(gè)屬性中將保存著響應(yīng)數(shù)據(jù)的XML DOM文檔(document形式)
status: HTTP狀態(tài)碼(數(shù)字形式)
statusText: HTTP狀態(tài)說明(文本形式)
xhr.onreadystatechange = function(){
if(xhr.readyState){
if(xhr.status>= 200 && xhr.status < 300 || xhr.status == 304){
}
}
}
關(guān)于xhr.status的解釋 : https://baike.baidu.com/item/HTTP%E7%8A%B6%E6%80%81%E7%A0%81/5053660?fr=aladdin
最后上一篇我自己封裝的ajax吧
const ajax = (json) => {
let xhr = null,
type = json.type.toUpperCase() || 'GET'; // 設(shè)置請(qǐng)求的默認(rèn)方法
// 兼容處理
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP')
}
// 設(shè)置請(qǐng)求時(shí)間的限制
xhr.timeout = json.time ? json.time : 0;
// 設(shè)置請(qǐng)求找過指定時(shí)間的時(shí)間
xhr.ontimeout = json.timeout ? json.timeout : null;
// 監(jiān)聽xhr對(duì)象額狀態(tài)
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
json.success(xhr.responseText) // 如果成功 即調(diào)用成功的回調(diào)函數(shù)
}else{
json.error&&json.error() // 失敗調(diào)用失敗的回調(diào)函數(shù)
}
}
}
if(type.toUpperCase() == 'GET'){
xhr.open('GET',json.url+'?'+toStr(json.data),true);
xhr.send()
}else if(type.toUpperCase() == 'POST'){
xhr.open('POST',json.url,true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send(toStr(json.data))
}
}
// 將對(duì)象的屬性和value轉(zhuǎn)換為 a:1&b:2
const toStr = json => {
var arr = [];
for(var i in json){
arr.push(i+'='+json[i])
}
return arr.join('&')
}