標籤:
1.Ajax1.1.Ajax簡介
Ajax簡介這一部分我們主要是談一下ajax的起源,ajax是什嗎?因為這些是跟技術無關的。所以,大多細節都是一筆帶過。
Ajax的起源?
Ajax一詞源於2005年 Jesse James Garrett發表的一篇題為"Ajax:A new Approach to Web Applications".他在這篇文 章中介紹了一種新技術,用他的話說,就是Ajax :Asynchronous JavaScript +XML的縮寫。
Ajax是什嗎?
這種新技術的主要目的就是為了使前端網頁能夠向伺服器請求額外的資料而不需要卸載頁面。自從這種技術出現以後,微軟率先引入XHRt對象(ajax能夠實現的核心對象),然後其他瀏覽器相繼實現這種技術。總而言之,ajax就是一種能非同步通訊的技術。
1.2.Ajax的核心對象---XMLHttpRequest
因為IE5是最先引入這個XHR對象的,當時並沒有事實上的標準。在IE中有三種不同的XHR對象版本:MSXML2.XMLHttp,MSXML2.XMLHttp.3.0和MSXML2.XMLHttp.6.0;
根據這三種版本號碼,在IE中建立一個XHR對象如下:
function createXHR() { //IE7之前的版本通過這種方式 var versions = [ ‘MSXML2.XMLHttp‘, ‘MSXML2.XMLHttp.3.0‘, ‘MSXML2.XMLHttp.6.0‘ ]; var xhr = null; for (var item in versions) { try { xhr = new ActiveXObject(item); //若不存在該版本,可能會出錯 if (xhr) break; } catch (e) { //一般對這種錯誤不做處理 } } return xhr;}
在IE引入這個對象之後,其他瀏覽器廠商也相繼跟隨,這時候XHR對象成為事實上的標準!
跨瀏覽器建立XHR對象;
function createXHttpRequest() { if (typeof XMLHttpRequest !== ‘undefined‘) { //不要用 if(XMLHttpRequest){}這種形式, return new XMLHttpRequest(); //如果是這種形式在找不到XMLHttpRequest函數的情況下,會報錯。
} else if (typeof ActiveXObject !== ‘undefined‘) {
return createXHR(); //用到剛才我們建立的函數
} else { throw new Error(‘不能建立XMLHttpRequest對象‘); } }
1.2.XMLHttpRequest的用法
XMLHttpRequest對象的函數有6個:
open("method",url,boolean);
//該方法的三個參數,分別為----提交方式"get"或者"post"等
//&& url是相對於執行代碼的當前頁面的路徑(使用絕對路徑是允許的)&&是否非同步
send();
//這個方法接收一個參數,這個參數是作為請求主體發送的資料,
//說明: 如果有參數,請使用post方式提交 使用方式如下,send("user="+username+"&pwd="+password); //如果沒有參數,為了相容性考慮,必須在參數中傳入null,即send(null);該方式使用get方式提交
abort(); //取消當前響應,關閉串連並且結束任何未決的網路活動。
//這個方法把 XMLHttpRequest 對象重設為 readyState 為 0 的狀態,並且取消所有未決 //的網路活動。例如,如果請求用了太長時間,而且響應不再必要的時候,可以調用這個方法。
getResponseHeader()
//返回指定的 HTTP 回應標頭部的值。其參數是要返回的 HTTP 回應標頭部的名稱。可以使用任 //何大小寫來制定這個頭部名字,和回應標頭部的比較是不區分大小寫。
//該方法的傳回值是指定的 HTTP 回應標頭部的值,如果沒有接收到這個頭部或者 readyStat //e 小於 3 則為空白字串。如果接收到多個有指定名稱的頭部,這個頭部的值被串連起來並 //返回,使用逗號和空格分隔開各個頭部的值。
getAllResponseHeaders()
//把 HTTP 回應標頭部作為未解析的字串返回。
//如果 readyState 小於 3,這個方法返回 null。否則,它返回伺服器發送的所有 HTTP 響應的
//頭部。頭部作為單個的字串返回,一行一個頭部。每行用分行符號 "\r\n" 隔開。
setRequestHeader()
//向一個開啟但未發送的請求設定或添加一個 HTTP 要求。
XMLHttpRequest對象的屬性有5個:
屬性 |
描述 |
responseText |
作為響應主題被返回的文本 |
responseXML |
如果相響應的是text/html或者application/xml類型的話,這個屬性將儲存著響應的XML文檔 |
status |
http的響應狀態代碼 |
statusText |
http狀態的說明 |
readyState |
XMLHttpRequest對象的狀態位 0 1 2 3 4 分別表示5種狀態 |
timeout |
設定逾時時間,單位是ms.目前只有IE8+支援---尚未標準化(不推薦使用) |
XMLHttpRequest對象的事件屬性onReadyStateChange:-----所有瀏覽器安全色
該屬性監聽的是 XMLHttpRequest對象的readyState屬性的變化:
readyState的變化分別對應如下狀態:
0:尚未初始化。未調用open()之前
1:啟動。調用open()之後,但是未調用send();
2:發送。調用send()但是尚未得到響應。
3:正在接收資料。剛接收到響應資料開始到接收完成之前。
4: 完成。資料接收完成。
xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status <== 300 || xhr.status == 304) { alert(xhr.responseText); //處理接收的資料 } else { //請求失敗,未得到響應資料 } }}; //補充說明:註冊事件必鬚髮生在send()以前
XMLHttpRequest對象的事件屬性ontimeout -----僅限IE8+,不過最新的主流高版本瀏覽器也已經實現(不推薦使用)
xhr.timeout=1000;//一秒鐘xhr.ontimeout=functon(){ //處理代碼 ......}
這種使用方式有個問題需要注意,就是在逾時之後,在接收到資料後仍然會觸發onreadystatechange事件,如果在處理onreadychange事件時訪問xhr.status屬性,會出錯。所以我們在訪問該屬性時需要做一下try{}catch處理。但是,因為這個屬性暫不相容,所有我們就不重點講了。
XMLHttpRequest對象的事件屬性onload onerror onloadstar onbort onprogress:
-----非IE瀏覽器和IE 10+已實現
onload在IE8以上可以實現,大部分事件根據readySate變化均可以實現,以上事件只不過是方便使用而已。
onload和onprogress 這兩種事件分別對應著readyState=4和readyState=3的情況,使用方式分別如下:
xhr.onload= function (event) { //event只包含一個屬性 event.target=xhr;使用方式只是在readyState=4時差不多.. } xhr.onprogress=function(event){ //event除了包含event.target=xhr之外,還包含三種屬性 //lengthComputale(進度資訊是否可用),position(已接受位元組數)和totalSize(總位元組數). }
補充:有些事件均可以根據readyState的狀態進行類比。只有有的瀏覽器進行了方便化處理而已。
3.單向跨域技術 ---CORS
今天我們這裡講的是用戶端網頁向不在同一個域的伺服器請求資料..用戶端在收到返回的資料時時,用回呼函數處理資料。
即:
1. 用戶端向域外伺服器請求資料
2.伺服器得到響應後向用戶端發送資料。
3.用戶端根據返回的資料執行回呼函數.
我知道不同域下的iframe也可以進行通訊,而且這也是一種跨域通訊技術。但是,這種iframe頁面之間的雙向通訊,我們在下一個專題裡面講解,今天主要講的是單向通訊。
3.1.CORS跨域請求的原理在用xhr(XMLHttpRequest)對象或者xdr(XDomainRequest)對象,發送域外請求時,大概的實現原理如: 3.2.IE中CORS技術的實現
IE8引入了一個XDR類型,這個類型與XHR基本類似,但是其能實現安全可靠地跨域通訊。
XHD的特點:
1.cookie不會隨請求發送,也不會隨響應返回。
2.只能佈建要求頭部中的Content-Type片段。
3.不能訪問回應標頭部資訊。
4.只是支援get和post請求。
XDR支援onload和onerror事件屬性,且其使用方式和XHR基本一致,不過其open()只接收兩個參數,預設是非同步。
var xdr = new XDomainRequest();xdr.onload = function () { //處理xdr.responseText}xdr.onerror = function () {};xdr.open(‘get‘, ‘絕對url‘);xhr.send(null);
3.3.跨瀏覽器的CORS技術實現
在標準瀏覽器中XHR對象就已經可以自動實現跨域請求,但是XHR和XDR的不同之處:
1.XHR可以在設定 withCredentials =true時,瀏覽器會把cookie發送給伺服器,伺服器此時通過設定頭部Access-Control-Allow-Credentials:true時來響應。如果,伺服器不設定這個屬性,則瀏覽器會觸發onerror事件。
2.在回呼函數中可以訪問status和statusText屬性,而且支援同步請求。
以下是實現跨域請求的代碼:
function createCrosRequest(method, url) { var xhr = new XMLHttpRequest(); //IE7+ if (‘withCredentials‘ in xhr) { //IE8-IE9瀏覽器沒有這個屬性 xhr.open(method, url, true); } else if (typeof XDomainRequest != ‘undefined‘) { xhr = new XDomainRequest(); //IE xhr.open(method, url) } return xhr;}
var request=CreateCrosRequest("get","url");
if(request){
request.onload=function(){
//處理request.responseText;
}
request.send(null);
}
4.單向跨域技術 ---JSONP技術
JSONP技術比較簡單,其主要原理主要是利用script標籤的特性。
script標籤和image標籤一樣,它們都具有src屬性,而且這個屬性是可跨域的。
因為script標籤返回的都是js代碼,且該js代碼會自動執行。所以,如果我們請求返回的資料也是類似一段js代碼的形式,豈不是就可以實現在指令碼載入完畢後自動執行。
如果我們的請求,返回的資料是 callback + ‘(‘ + json + ‘)‘; 這種形式的資料, 那麼在指令碼載入完畢之後也就能自動執行callback()函數了.
4.1.用戶端寫法
<!DOCTYPE html><html><head> <meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body> <button id="button">請求資料</button></body><script> window.onload=function(){ var button=document.getElementById("ibutton"); function callback(data){ //處理data } button.onclick=function(){ var script=document.createElement("script"); script="http://www.sasd.com/json/?callbak=callback"; document.body.insertBefore(script,document.body.firstChild);//載入指令碼 } }</script></html>
1.用戶端將回呼函數名寫入<Script>指令碼的url參數中。
2.script載入的時候會發送跨域請求。
4.2.伺服器端
1.通過url得到函數名,命名為callback
2.將請求的資料作為函數的參數格式轉化json格式,命名為。
3.將返回結果拼接為 callback+"("+json+")"; --------返回的就是填充式的資料,這段資料在指令碼中會自動執行。
4.返回資料.
4.3.JSONP技術的缺點
1.因為是通過url傳參數,所以請求只能是get類型的。
2.<script>目前只有onload屬性事件,onerror還沒有統一化,如果載入指令碼出錯,用戶端很難得到反饋。
3.所請求資料的網站必須是可信任的,如果返回的資料區段中注入的有惡意的代碼,危害較大,且難以發現。
JavaScript系列----AJAX以及跨域通訊