ajax 即「Asynchronous Javascript And XML」(異步 JavaScript 和 XML),是指一種建立交互式網頁應用的網頁開發技術。當初JavaScript的變革就是ajax的出現而改變。在現代web領域對數據的異步加載和局部更新上也在大量採用ajax這項技術。
目前瀏覽器在使用ajax技術上都是使用XMLHttpRequest(XHR)對象來對服務器進行交互。對於IE低版本(6/7)上則是使用的另外一種實現方式(ActiveXObject),咱們能夠從URL獲取數據,而不用讓整個頁面刷新,從而實現局部刷新。這樣請求的次數也會大大減小,有效節約資源浪費。XMLHttpRequest的交互原理則是XMLHttpRequst請求事件目標(XMLHttpRequestEventTarget)從而到達後端事件目標。事件目標對請求事件進行驗證明現業務邏輯,最後能夠響應處理結果與前端交互。XMLHttpRequest不光能請求XML類型的數據(文本、圖片、html,信息流等),一樣還支持HTTP之外的協議,好比文件流和ftp等等。相似的還有WebSockets(全雙工通訊),Server-Sent event(HTML5服務器發送事件)。
在使用XMLHttpRequest
以前咱們須要初始化一個XMLHttpRequest
對象,才能使用它的屬性和方法。javascript
經常使用方法和屬性:php
// 初始化對象,將最早調用該對象的構造函數 var oReq = new XMLHttpRequest(); oReq.open(method,url,async); // 初始化一個請求,例如 oReq.open('GET',url,true) ++++++++++++++++++++++++++++++++++++++++++ function reqListener () { console.log(this.responseText); } var oReq = new XMLHttpRequest(); oReq.onload = reqListener; // 請求加載完成調用此方法 oReq.open("get", "yourFile.txt", true); oReq.send(); // XMLHttpRequest一樣也支持多種時間綁定,第一個參數爲觸發時間,第二個參數爲綁定執行函數 var req = new XMLHttpRequest(); req.addEventListener("progress", updateProgress, false); req.addEventListener("load", transferComplete, false); req.addEventListener("error", transferFailed, false); req.addEventListener("abort", transferCanceled, false); req.open(); //注意:必須在open()以前添加事件監聽,不然progress(進度)事件將不會被觸發 // 此外XMLHttpRequest還可以接收二進制數據,具體操做能夠閱讀相關文檔 var BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder || window.BlobBuilder; var oReq = new XMLHttpRequest(); oReq.open("GET", "/myfile.png", true); oReq.responseType = "arraybuffer"; oReq.onload = function(oEvent) { var blobBuilder = new BlobBuilder(); blobBuilder.append(oReq.response); var blob = blobBuilder.getBlob("image/png"); // ... }; oReq.send(); +++++++++++++++++++++++++++++++++++++++++++++ oReq.setRequestHeader(header,value); //針對post方法須要設置頭部信息纔能有效解析參數 oReq.setRequestHeader('content-type','application/x-www-form-urlencoded'); oReq.send()方法,若是是get協議能夠爲空,可是若是是post協議,則傳遞給服務端的參數須要在這裏面指定 xhr.send("foo=bar&lorem=ipsum"); // post表單數據能夠經過for/in拼接字符串來進行 // xhr.send('string'); // xhr.send(new Blob()); // xhr.send(new Int8Array()); // xhr.send({ form: 'data' }); // xhr.send(document); oReq.onreadystatechange = fn; // 在readyStatus屬性狀態發生改變時觸發 // 當readyStatus就緒狀態發生改變時調用函數,狀態有0-4 xhr.onreadystatechange = function() { if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) { // 請求結束後,在此處寫處理代碼 } } oReq.response // 返回響應的正文,它和reponseText的區別是,response還能夠是其餘類型的數據,不光是文本類型 oReq.responseText // 請求成功會返回一個響應的字符串,若是發送失敗或未發送則返回null var xhr = new XMLHttpRequest(); xhr.open('GET', '/server', true); // If specified, responseType must be empty string or "text" xhr.responseType = 'text'; xhr.onload = function () { if (xhr.readyState === xhr.DONE) { if (xhr.status === 200) { console.log(xhr.response); console.log(xhr.responseText); } } }; xhr.send(null); // 返回一個無符號請求響應狀態,好比 200,304,501,404 oReq.status 其餘屬性和方法咱們能夠打印XMLHttpRequest對象或者參考官方文檔來進行使用
須要注意緩存問題和編碼,針對中文能夠使用url編碼工具進行處理,對於緩存問題能夠使用添加時間隨機數來解決。html
var xhr = new XMLHttpRequest(); // 第三個參數爲true則使用異步I/O處理方式,fase爲同步I/O處理方式(阻塞式,在沒有響應數據返回時程序會等待) xhr.open('get','index.php?username'+encodeURI('嚴總')+'&age=30&'+ new Date().getTime(),true); xhr.send(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ consoel.log(xhr.responseText); } else { console.log('status:'+xhr.status); return false; } };
聲明瞭請求頭以後會自動進行編碼,也沒有緩存問題前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> </style> </head> <body> <input type="button" id="btn" value="request"> </body> <script> var oBtn = document.querySelector('#btn'); var userData = { username:'boole', age:30, address:'china' }; oBtn.addEventListener('click',function(){ var xhr = null; // 兼容低版本IE,這裏使用異常處理分支完成,防止報錯阻斷程序運行 try{ xhr = new XMLHttpRequest(); } catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } xhr.open('post','index.php',true); xhr.setRequestHeader('content-type','application/x-www-form-urlencoded'); xhr.send(changeData(userData)); xhr.onreadystatechange = function(){ if(xhr.readyState ==4){ console.log(xhr.responseText); //字符串形式的響應數據須要進行轉換成對象才能使用 console.log(JSON.parse(xhr.responseText).username); // 也能夠使用eval預執行的方式進行轉換 var responseData = eval('('+xhr.responseText+')'); for(item in responseData){ console.log(item + '=' + responseData[item]); } } else { console.log(xhr.status); } }; }); function changeData(oData){ var str = ''; for(item in oData){ str += '&' + item + '=' + oData[item]; } return str.slice(1); } </script> </html>
後臺在接收到數據以後,在返回數據的時候能夠使用json的格式進行返回(例如:echo json_encode($arr);)java
注意: 後端返回的responseText老是字符串格式,直接使用屬性方法是不能獲取到數據的,咱們須要對響應的數據進行格式轉換。
方法有兩種,若是後端返回的是json格式的,那麼XMLHttpRequest接收的時候迴轉換成字符串形式的,
咱們能夠使用JSON.parse(str) 和 eval('('+str+')')進行轉換成json對象的形式,這樣一來咱們就能夠使用for/in對數據進行迭代處理。能夠動態更新頁面數據web
// 此處回提示undefined,由於是字符串形式的數據 console.log(xhr.responseText.username); // 轉換方式一 var reponseData = JSON.parse(xhr.responseText); // 抓換方式二 var reponseData = eval('('+xhr.responseText+')');
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> <style> </style> </head> <body> <input type="button" id="btn" value="request" /> <ul id="ul"></ul> <script> var oBtn = document.querySelector('#btn'); var userData = { username:'boole', age:30, address:'china' }; oBtn.addEventListener('click',function(){ // 定時請求局部更新 setInterval( ajax('post','index.php',userData,function(data){ var data = JSON.parse(data); var oUl = document.querySelector('#ul'); var aLi = ''; for (item in data){ aLi +='<li>' + item + '[' + data[item] + ']</li>'; } oUl.innerHTML = aLi,document.innerHTML = oUl; }),2000 ); }); // ajax函數封裝,對可變數據設置形參 function ajax(method,url,data,success){ var str = '',xhr = null; if(data instanceof Array || (typeof data == 'string')){ console.log('parameter type error'); return false; } else { for(item in data){ str += '&' + item + '=' + data[item]; } str = str.slice(1); } console.log(str); // 兼容低版本IE,這裏使用異常處理分支完成,防止報錯阻斷程序運行 try{ xhr = new XMLHttpRequest(); } catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } if(method == 'get' && data){ url += '?' + str + '&' + new Date().getTime(); } xhr.open(method,url,true); if(method == 'get'){ xhr.send(); } else { xhr.setRequestHeader('content-type','application/x-www-form-urlencoded'); xhr.send(str); } xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(xhr.status == 200){ console.log(xhr.responseText); success && success(xhr.responseText); } else { alert('請求失敗,狀態碼:'+ xhr.status); } } }; } </script> </body> </html>