生活随笔
收集整理的這篇文章主要介紹了
jquery.ajax
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
這所有的最終都是通過(guò)jQuery.ajax()來(lái)完成的。 ??ajax?:?function(s)?{ ????????????s?=?jQuery.extend(true,?s,?jQuery.extend(true,?{},? ??jQuery.ajaxSettings,????s));?????????① ??????var?jsonp,?jsre?=?/=\?(&|$)/g,?status,?data, ???type?=?s.type??.toUpperCase(); ????if?(s.data?&&?s.processData?&&?typeof?s.data?!=?"string") ??????????s.data?=?jQuery.param(s.data); ??????if?(s.dataType?==?"jsonp")?{???????????????????????????????② ??if?(type?==?"GET")?{??????????if?(!s.url.match(jsre)) ??????????????s.url?+=?(s.url.match(/\?/)???"&"?:?"?") ??????????????????????????????+?(s.jsonp?||?"callback")?+?"=?"; ??????????????}???else?if?(!s.data?||?!s.data.match(jsre)) ??????????s.data?=?(s.data???s.data?+?"&"?:?"")?+?(s.jsonp||"callback")+?"=?"; ??s.dataType?=?"json"; ??}??????? ????if?(s.dataType?==?"json"?? ??????????????&&?(s.data?&&?s.data.match(jsre)?||?s.url.match(jsre)))?{③ ???????jsonp?=?"jsonp"?+?jsc++; ??/?/為請(qǐng)求字符集串的callback=加上生成回調(diào)函數(shù)名 ??????if?(s.data)s.data?=?(s.data?+?"").replace(jsre,?"="?+?jsonp?+?"$1"); ??????s.url?=?s.url.replace(jsre,?"="?+?jsonp?+?"$1"); ??????????????????????????????????s.dataType?=?"script"; ??????????????window[jsonp]?=?function(tmp)?{ ??????????data?=?tmp;success();complete(); ???????????????window[jsonp]?=?undefined; ??????????try?{???delete?window[jsonp]; ??????????????}?catch?(e)?{???} ??????????if?(head)???head.removeChild(script); ??????????}; ??????} ????if?(s.dataType?==?"script"?&&?s.cache?==?null)??s.cache?=?false; ????if?(s.cache?===?false?&&?type?==?"GET")?{ ??????var?ts?=?now(); ??????var?ret?=?s.url.replace(/(\?|&)_=.*?(&|$)/,?"$1_="?+?ts?+?"$2"); ????????????s.url?=?ret+?((ret?==?s.url)???(s.url.match(/\?/)???"&"?:?"?")?+?"_="??????????????????????????+?ts?:?""); ??????} ????if?(s.data?&&?type?==?"GET")?{ ??????????s.url?+=?(s.url.match(/\?/)???"&"?:?"?")?+?s.data; ????????????????????s.data?=?null; ??????????} ????if?(s.global?&&?!jQuery.active++)?jQuery.event.trigger("ajaxStart");④ ????var?parts?=?/^(\w+:)?\/\/([^\/?#]+)/.exec(s.url); ??????if?(s.dataType?==?"script"??&&?type?==?"GET"&&?parts????&&?(parts[1]?&&? ??parts[1]?!=?location.protocol?||?parts[2]?!=?location.host))?{⑤ ????????????????????var?head?=?document.getElementsByTagName("head")[0]; ??????????var?script?=?document.createElement("script"); ??????????script.src?=?s.url; ??????????if?(s.scriptCharset)????script.charset?=?s.scriptCharset; ?????????????????????????????if?(!jsonp)?{ ??????????????var?done?=?false; ????????????????????????????script.onload?=?script.onreadystatechange?=?function()?{ ??????????????if?(!done&&?(!this.readyState?||?this.readyState?==?"loaded"? ??||?this.readyState?==?"complete"))?{ ??????????????????????done?=?true;????success(); ??????????????????????complete();head.removeChild(script); ??????????????????} ??????????}; ??????} ??????head.appendChild(script); ????????return?undefined; ??} ??var?requestDone?=?false; ????var?xhr?=?window.ActiveXObject???????????????????????????????⑥ ????????????new?ActiveXObject("Microsoft.XMLHTTP"):?new?XMLHttpRequest(); ????if?(s.username)xhr.open(type,?s.url,?s.async,?s.username,?s.password); ??else????xhr.open(type,?s.url,?s.async); ????try?{??????if?(s.data) ??????????xhr.setRequestHeader("Content-Type",?s.contentType); ????????????????if?(s.ifModified) ??????????xhr.setRequestHeader("If-Modified-Since", ??????????????jQuery.lastModified[s.url]||?"Thu,?01?Jan?1970?00:00:00?GMT"); ????????xhr.setRequestHeader("X-Requested-With",?"XMLHttpRequest"); ????????xhr.setRequestHeader("Accept",?s.dataType?&&?s.accepts[s.dataType] ????????????????s.accepts[s.dataType]?+?",?*/*":?s.accepts._default); ??}?catch?(e)?{} ????if?(s.beforeSend?&&?s.beforeSend(xhr,?s)?===?false)?{?????????⑧ ????????????s.global?&&?jQuery.active--; ??????xhr.abort(); ??????return?false; ??} ??????if?(s.global)???jQuery.event.trigger("ajaxSend",?[xhr,?s]); ????var?onreadystatechange?=?function(isTimeout)?{???????????⑨ ????if?(!requestDone?&&?xhr&&?(xhr.readyState?==?4?||isTimeout?==?"timeout"))?{?requestDone?=?true; ?????????????????????if?(ival)?{clearInterval(ival);?????ival?=?null;????} ????????????status?=?isTimeout?==?"timeout"???"timeout"?:?!jQuery ??????????ttpSuccess(xhr)???"error"?:?s.ifModified&&?jQuery. ??httpNotModified(xhr,?s.url)???"notmodified":?"success"; ????????????????if?(status?==?"success")?{?????????????????? ??????????try?{???data?=?jQuery.httpData(xhr,?s.dataType,?s); ???????????????}?catch?(e)?{??status?=?"parsererror";?} ??????} ????????if?(status?==?"success")?{ ??????????var?modRes; ????????????try?{modRes?=?xhr.getResponseHeader("Last-Modified"); ??????????????}?catch?(e)?{????????????????????????if?(s.ifModified?&&?modRes)jQuery.lastModified[s.url]?=?modRes; ???????????????????if?(!jsonp)?success(); ??????}?else????????jQuery.handleError(s,?xhr,?status); ????????complete(); ??if?(s.async)????xhr?=?null;???} ??}; ??if?(s.async)?{ ??????var?ival?=?setInterval(onreadystatechange,?13); ????????if?(s.timeout?>?0) ??????????setTimeout(function()?{????????????????? ??????????????if?(xhr)?{??xhr.abort(); ??????????????????if?(!requestDone)???onreadystatechange("timeout");??} ??????????},?s.timeout); ??????} ????try?{xhr.send(s.data);?catch(e){jQuery.handleError(s,xhr,null,e);}?⑩ ????if?(!s.async)???onreadystatechange(); ??function?success()?{ ????????????if?(s.success)??s.success(data,?status); ????????????if?(s.global)???jQuery.event.trigger("ajaxSuccess",?[xhr,?s]); ??????} ??function?complete()?{ ????????????if?(s.complete)?s.complete(xhr,?status); ????????????if?(s.global)???jQuery.event.trigger("ajaxComplete",?[xhr,?s]); ????????????if?(s.global?&&?!--jQuery.active)jQuery.event.trigger("ajaxStop"); ??????} ????return?xhr; ??}, ??Jquery.ajax是大包大攬的非常復(fù)雜的一個(gè)方法。它并沒(méi)有像其它的lib一樣,把每個(gè)小部分都分開來(lái)。它是整個(gè)都整在一個(gè)函數(shù)中??雌饋?lái)很多,實(shí)際上上也沒(méi)有脫離前面所說(shuō)的ajax的請(qǐng)求的五步。它的很大一部分代碼在處理跨域請(qǐng)求的處理上。下面就分別就ajax的代碼進(jìn)行分析。 ??ajaxSettings ??在①處通過(guò)繼承的方式把傳入?yún)?shù)s和默認(rèn)的jQuery.ajaxSettings都clone到s變量中。S的同名屬性會(huì)覆蓋jQuery.ajaxSettings的同名屬性。這里兩次繼承s,以便在測(cè)試中能檢測(cè)。 ????????ajaxSettings?:?{ ??????????url?:?location.href,??????????global?:?true,??????????type?:?"GET", ??????????timeout?:?0, ??????????contentType?:?"application/x-www-form-urlencoded",?? ???????processData?:?true, ??????????async?:?true, ??????????data?:?null, ??????????username?:?null, ??????????password?:?null, ??????????accepts?:?{ ??????????????xml?:?"application/xml,?text/xml", ??????????????html?:?"text/html", ??????????????script?:?"text/javascript,?application/javascript", ??????????????json?:?"application/json,?text/javascript", ??????????????text?:?"text/plain", ??????????????_default?:?"*/*"??????????} ??這是默認(rèn)的ajax的設(shè)定,我們要在參數(shù)s設(shè)定同名的屬性來(lái)覆蓋這些屬性。但是我們不能覆蓋accepts。這個(gè)會(huì)在后面的代碼用到。我們可以通過(guò)設(shè)定s.dataType等于accepts中的某一個(gè)屬性key指定請(qǐng)求的data類型,如xml,html,script,json,text。dataType還支持默認(rèn)的_default和跨域的jsonp。不過(guò)其最終會(huì)解析成script。 ??scriptTag ??②~⑥是處理跨域請(qǐng)求的部分。對(duì)于dataType為jsonp的類型,給其請(qǐng)求的字符串(可能是s.data)加上callback=callbackfn的key/value串,然后在window下注冊(cè)一個(gè)callbackfn的函數(shù)。這個(gè)函數(shù)的形式如callbackfn(data){?data?=?tmp;success();complete();}。它代理了通過(guò)ajax(s)的傳入s參數(shù)中success();complete()的功能。它就是調(diào)用這個(gè)函數(shù),實(shí)際上是調(diào)用success();complete()的函數(shù)。 ??那么怎么調(diào)用呢?ajax不支持跨域。在⑤處,我們可以看到這里是采用scriptTag的方式來(lái)完成。先在頁(yè)面的<head>中添加一個(gè)<script?src=url?/>的標(biāo)簽。因?yàn)樵?lt;head>中。瀏覽器會(huì)自動(dòng)載入并運(yùn)行請(qǐng)求返回的script。如果是jsonp的形式,服務(wù)器端還要?jiǎng)討B(tài)生成的content-type為script的代碼:callbackfn(data);只有這樣才會(huì)調(diào)用在window中注冊(cè)的函數(shù)callbackfn。同時(shí)傳入所需要的參數(shù)。 ??如dataType?==?"script"形式的跨域,那只能是通過(guò)script.onload?或?script.onreadystatechange事件來(lái)觸發(fā)回調(diào)。這里我們可以通過(guò)服務(wù)器返回的script代碼:var?data=xxx。來(lái)傳遞參數(shù)給s.success();s.complete()。Jquery這里采用是全局變量data來(lái)進(jìn)行操作的。 ??Ajax?Event ??④是采用了jQuery.event.trigger("ajaxStart");來(lái)觸發(fā)全局的ajaxStart事件。這也是說(shuō)只要注冊(cè)了這個(gè)事件的元素,在任何的ajax的請(qǐng)求時(shí)ajaxStart都會(huì)執(zhí)行元素注冊(cè)的事件處理函數(shù)。這和Ext的事件有點(diǎn)相似。但是它不是全局的。 ??jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),?function(i,?o)?{ ??????jQuery.fn[o]?=?function(f)?{??????????return?this.bind(o,?f); ??????}; ??上面的代碼是為jquery對(duì)象注冊(cè)了ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend這幾種ajax的事件方法,在jquery.ajax中不同的時(shí)刻都會(huì)觸發(fā)這些事件。當(dāng)然我們也可以采用s.global=false來(lái)設(shè)定不觸發(fā)這些事件。 ??因?yàn)檫@是全局的,個(gè)人認(rèn)為其設(shè)計(jì)的目的就是為了在這些時(shí)候能以某種形式來(lái)告訴用戶ajax的進(jìn)行的狀態(tài)。如在ajaxstart的時(shí)候,我們可能通過(guò)一個(gè)topest的div層(加上遮罩的效果)的元素注冊(cè)一個(gè)ajaxstart事件的處理方法。該方法就是顯示這個(gè)層和顯示“你的數(shù)據(jù)正在提交。。?!边@個(gè)的提示。這是這6種事件的最佳用法了。 ??如果進(jìn)行私有處理,那么要在事件的處理函數(shù)中進(jìn)行判斷。因?yàn)槊總€(gè)事件處理函數(shù)的第二參數(shù)是jquery.ajax(s)的s參數(shù)。我們可以在這個(gè)參數(shù)中做私有的標(biāo)識(shí),如eventType:xxx。每類不同的請(qǐng)求有不同的eventType值。在事件處理函數(shù)再根據(jù)這個(gè)eventType==xxx進(jìn)行判斷,從而進(jìn)行私有的處理。如果有大量的這樣的私有處理也是會(huì)影響ajax的效率的。 ??setRequestHeader ??⑥處是創(chuàng)建一個(gè)xhr對(duì)象并通過(guò)open來(lái)創(chuàng)建一個(gè)連接(socket)。 ??⑦處是設(shè)定請(qǐng)求的頭部(setRequestHeader)。如果data的存在的話,那就得設(shè)定Content-Type,便于服務(wù)器按一定的規(guī)則來(lái)解碼??梢钥闯鰌ost的方式通過(guò)data傳遞數(shù)據(jù)要安全一點(diǎn)。 ??那么服務(wù)器如果區(qū)別這個(gè)請(qǐng)求是ajax呢?因?yàn)橥胶彤惒絘jax的請(qǐng)求的頭文件是一樣的。我們?nèi)绻ㄟ^(guò)X-Requested-With"="XMLHttpRequest”來(lái)標(biāo)識(shí)這個(gè)請(qǐng)求是ajax的請(qǐng)求。如果服務(wù)器硬是要區(qū)分的話,就可以通過(guò)獲取該頭部來(lái)判斷。 ??在頭部的定義中,還可能通過(guò)Accept來(lái)指定接受的數(shù)據(jù)的類型,如application/xml,?text/xml",?"text/html",?"text/javascript,?等等。 ??頭部還有一個(gè)If-Modified-Since的屬性用來(lái)提高效率的。它和”Last-Modified配合起來(lái)使用。在瀏覽器第一次請(qǐng)求某一個(gè)URL時(shí),服務(wù)器端的返回狀態(tài)會(huì)是200,內(nèi)容是你請(qǐng)求的資源,同時(shí)有一個(gè)Last-Modified的屬性標(biāo)記此文件在服務(wù)期端最后被修改的時(shí)間,格式類似這樣:Last-Modified:?Fri,?12?May?2006?18:53:33?GMT? ??客戶端第二次請(qǐng)求此URL時(shí),根據(jù)?HTTP?協(xié)議的規(guī)定,瀏覽器會(huì)向服務(wù)器傳送?If-Modified-Since?報(bào)頭,詢問(wèn)該時(shí)間之后文件是否有被修改過(guò):??If-Modified-Since:?Fri,?12?May?2006?18:53:33?GMT????如果服務(wù)器端的資源沒(méi)有變化,則自動(dòng)返回?HTTP?304?(Not?Changed.)狀態(tài)碼,內(nèi)容為空,這樣就節(jié)省了傳輸數(shù)據(jù)量。 ??當(dāng)服務(wù)器端代碼發(fā)生改變或者重啟服務(wù)器時(shí),則重新發(fā)出資源,返回和第一次請(qǐng)求時(shí)類似。從而保證不向客戶端重復(fù)發(fā)出資源,也保證當(dāng)服務(wù)器有變化時(shí),客戶端能夠得到最新的資源。 ??攔截處理 ??⑧處是一個(gè)send之前的攔截處理,可以通過(guò)s.?beforeSend(xhr,?s)函數(shù)的形式傳入攔截函數(shù)。保證在發(fā)送之前確保滿足某些條件。在取得返回?cái)?shù)據(jù)的時(shí)候,也可以通過(guò)s.dataFilter(data,?type);形式來(lái)攔截處理data。不過(guò)這里主要的作用對(duì)data進(jìn)一步的篩選。 ??onreadystatechange ??⑨處是onreadystatechange的回調(diào)處理。這里采用是poll的形式進(jìn)行處理。它把返回的狀態(tài)分成status:tiemout-->error-->notmodified-->success—>parsererror這幾種。如果status?==?"success"那么分析這些數(shù)據(jù)之后再進(jìn)行l(wèi)ast-modified相關(guān)的處理。為了不取回沒(méi)有修改過(guò)數(shù)據(jù)。 ??分析數(shù)據(jù)的代碼如下: ????????httpData?:?function(xhr,?type,?s)?{ ??????????var?ct?=?xhr.getResponseHeader("content-type"),? ????????????xml?=?type?==?"xml"???||?!type?&&?ct?&&?ct.indexOf("xml")?>=?0,? ?????????????data?=?xml??xhr.responseXML??:?xhr.responseText; ??????????if?(xml?&&?data.documentElement.tagName?==?"parsererror") ??????????????throw?"parsererror"; ????????????????????if?(s?&&?s.dataFilter) ??????????????data?=?s.dataFilter(data,?type); ????????????????????????????if?(type?==?"script")???jQuery.globalEval(data); ????????????????????if?(type?==?"json")?????data?=?eval("("?+?data?+?")"); ??????????return?data; ??????}, ??如果返回的content-type是xml,html,text等都返回。對(duì)script執(zhí)行jQuery.globalEval來(lái)執(zhí)行它。對(duì)于Json類型,通過(guò)eval來(lái)生成返回的json對(duì)象。 ????globalEval?:?function(data)?{ ??????data?=?jQuery.trim(data); ??????????if?(data)?{ ????????????var?head?=?document.getElementsByTagName("head")[0] ??????????????????????????||?document.documentElement, ??????????script?=?document.createElement("script"); ??????script.type?=?"text/javascript"; ??????if?(jQuery.browser.msie)????script.text?=?data; ??????else????script.appendChild(document.createTextNode(data)); ????????????????????????head.insertBefore(script,?head.firstChild); ??????????head.removeChild(script); ??????????????}???????}, ????????????????????
總結(jié)
以上是生活随笔為你收集整理的jquery.ajax的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。