畅游Python 二十二:网页开发技术方案:AJAX
一、概述
對(duì)于WEB應(yīng)用程序而言:用戶瀏覽器發(fā)送請(qǐng)求,服務(wù)器接收并處理請(qǐng)求,然后返回結(jié)果,往往返回的是字符串(HTML),瀏覽器將字符串(HTML)渲染并顯示在瀏覽器上。
1、傳統(tǒng)的Web應(yīng)用
一個(gè)簡(jiǎn)單操作需要重新加載全局?jǐn)?shù)據(jù)
2、AJAX
AJAX,Asynchronous JavaScript and XML (異步的JavaScript和XML),一種創(chuàng)建交互式網(wǎng)頁(yè)應(yīng)用的網(wǎng)頁(yè)開(kāi)發(fā)技術(shù)方案。
- 異步的JavaScript:
使用 【JavaScript語(yǔ)言】 以及 相關(guān)【瀏覽器提供類(lèi)庫(kù)】 的功能向服務(wù)端發(fā)送請(qǐng)求,當(dāng)服務(wù)端處理完請(qǐng)求之后,【自動(dòng)執(zhí)行某個(gè)JavaScript的回調(diào)函數(shù)】。
PS:以上請(qǐng)求和響應(yīng)的整個(gè)過(guò)程是【偷偷】進(jìn)行的,頁(yè)面上無(wú)任何感知。 - XML
XML是一種標(biāo)記語(yǔ)言,是Ajax在和后臺(tái)交互時(shí)傳輸數(shù)據(jù)的格式之一
利用AJAX可實(shí)現(xiàn):
1、注冊(cè)時(shí),輸入用戶名自動(dòng)檢測(cè)用戶是否已經(jīng)存在。
2、登陸時(shí),提示用戶名密碼錯(cuò)誤
3、刪除數(shù)據(jù)行時(shí),將行ID發(fā)送到后臺(tái),后臺(tái)在數(shù)據(jù)庫(kù)中刪除,數(shù)據(jù)庫(kù)刪除成功后,在頁(yè)面DOM中將數(shù)據(jù)行也刪除。
二、偽AJAX
由于HTML標(biāo)簽的iframe標(biāo)簽具有局部加載內(nèi)容的特性,所以可以使用其來(lái)偽造Ajax請(qǐng)求。
<!DOCTYPE html> <html><head lang="en"><meta charset="UTF-8"><title></title></head><body><div><p>請(qǐng)輸入要加載的地址:<span id="currentTime"></span></p><p><input id="url" type="text" /><input type="button" value="刷新" onclick="LoadPage();"></p></div><div><h3>加載頁(yè)面位置:</h3><iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe></div><script type="text/javascript">window.onload= function(){var myDate = new Date();document.getElementById('currentTime').innerText = myDate.getTime();};function LoadPage(){var targetUrl = document.getElementById('url').value;document.getElementById("iframePosition").src = targetUrl;}</script></body> </html>三、原生AJAX
Ajax主要就是使用 【XmlHttpRequest】對(duì)象來(lái)完成請(qǐng)求的操作,該對(duì)象在主流瀏覽器中均存在(除早起的IE),Ajax首次出現(xiàn)IE5.5中存在(ActiveX控件)。
1. XmlHttpRequest對(duì)象介紹
XmlHttpRequest對(duì)象的主要方法:
a. void open(String method,String url,Boolen async)用于創(chuàng)建請(qǐng)求參數(shù):method: 請(qǐng)求方式(字符串類(lèi)型),如:POST、GET、DELETE...url: 要請(qǐng)求的地址(字符串類(lèi)型)async: 是否異步(布爾類(lèi)型)b. void send(String body)用于發(fā)送請(qǐng)求參數(shù):body: 要發(fā)送的數(shù)據(jù)(字符串類(lèi)型)c. void setRequestHeader(String header,String value)用于設(shè)置請(qǐng)求頭參數(shù):header: 請(qǐng)求頭的key(字符串類(lèi)型)vlaue: 請(qǐng)求頭的value(字符串類(lèi)型)d. String getAllResponseHeaders()獲取所有響應(yīng)頭返回值:響應(yīng)頭數(shù)據(jù)(字符串類(lèi)型)e. String getResponseHeader(String header)獲取響應(yīng)頭中指定header的值參數(shù):header: 響應(yīng)頭的key(字符串類(lèi)型)返回值:響應(yīng)頭中指定的header對(duì)應(yīng)的值f. void abort()終止請(qǐng)求XmlHttpRequest對(duì)象的主要屬性包括:
a. Number readyState狀態(tài)值(整數(shù))詳細(xì):0-未初始化,尚未調(diào)用open()方法;1-啟動(dòng),調(diào)用了open()方法,未調(diào)用send()方法;2-發(fā)送,已經(jīng)調(diào)用了send()方法,未接收到響應(yīng);3-接收,已經(jīng)接收到部分響應(yīng)數(shù)據(jù);4-完成,已經(jīng)接收到全部響應(yīng)數(shù)據(jù);b. Function onreadystatechange當(dāng)readyState的值改變時(shí)自動(dòng)觸發(fā)執(zhí)行其對(duì)應(yīng)的函數(shù)(回調(diào)函數(shù))c. String responseText服務(wù)器返回的數(shù)據(jù)(字符串類(lèi)型)d. XmlDocument responseXML服務(wù)器返回的數(shù)據(jù)(Xml對(duì)象)e. Number states狀態(tài)碼(整數(shù)),如:200、404...f. String statesText狀態(tài)文本(字符串),如:OK、NotFound...2. 跨瀏覽器支持
- XmlHttpRequest
IE7+, Firefox, Chrome, Opera, etc. - ActiveXObject("Microsoft.XMLHTTP")
IE6, IE5
?四、jQuery Ajax
jQuery其實(shí)就是一個(gè)JavaScript的類(lèi)庫(kù),其將復(fù)雜的功能做了上層封裝,使得開(kāi)發(fā)者可以在其基礎(chǔ)上寫(xiě)更少的代碼實(shí)現(xiàn)更多的功能。
- jQuery 不是生產(chǎn)者,而是大自然搬運(yùn)工。
- jQuery Ajax本質(zhì) XMLHttpRequest 或 ActiveXObject?
注:2.+版本不再支持IE9以下的瀏覽器
jQuery Ajax 方法列表:
jQuery.get(...)所有參數(shù):url: 待載入頁(yè)面的URL地址data: 待發(fā)送 Key/value 參數(shù)。success: 載入成功時(shí)回調(diào)函數(shù)。dataType: 返回內(nèi)容格式,xml, json, script, text, htmljQuery.post(...)所有參數(shù):url: 待載入頁(yè)面的URL地址data: 待發(fā)送 Key/value 參數(shù)success: 載入成功時(shí)回調(diào)函數(shù)dataType: 返回內(nèi)容格式,xml, json, script, text, htmljQuery.getJSON(...)所有參數(shù):url: 待載入頁(yè)面的URL地址data: 待發(fā)送 Key/value 參數(shù)。success: 載入成功時(shí)回調(diào)函數(shù)。jQuery.getScript(...)所有參數(shù):url: 待載入頁(yè)面的URL地址data: 待發(fā)送 Key/value 參數(shù)。success: 載入成功時(shí)回調(diào)函數(shù)。jQuery.ajax(...)部分參數(shù):url:請(qǐng)求地址type:請(qǐng)求方式,GET、POST(1.9.0之后用method)headers:請(qǐng)求頭data:要發(fā)送的數(shù)據(jù)contentType:即將發(fā)送信息至服務(wù)器的內(nèi)容編碼類(lèi)型(默認(rèn): "application/x-www-form-urlencoded; charset=UTF-8")async:是否異步timeout:設(shè)置請(qǐng)求超時(shí)時(shí)間(毫秒)beforeSend:發(fā)送請(qǐng)求前執(zhí)行的函數(shù)(全局)complete:完成之后執(zhí)行的回調(diào)函數(shù)(全局)success:成功之后執(zhí)行的回調(diào)函數(shù)(全局)error:失敗之后執(zhí)行的回調(diào)函數(shù)(全局)accepts:通過(guò)請(qǐng)求頭發(fā)送給服務(wù)器,告訴服務(wù)器當(dāng)前客戶端課接受的數(shù)據(jù)類(lèi)型dataType:將服務(wù)器端返回的數(shù)據(jù)轉(zhuǎn)換成指定類(lèi)型"xml": 將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成xml格式"text": 將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成普通文本格式"html": 將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成普通文本格式,在插入DOM中時(shí),如果包含JavaScript標(biāo)簽,則會(huì)嘗試去執(zhí)行。"script": 嘗試將返回值當(dāng)作JavaScript去執(zhí)行,然后再將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成普通文本格式"json": 將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成相應(yīng)的JavaScript對(duì)象"jsonp": JSONP 格式使用 JSONP 形式調(diào)用函數(shù)時(shí),如 "myurl?callback=?" jQuery 將自動(dòng)替換 ? 為正確的函數(shù)名,以執(zhí)行回調(diào)函數(shù)如果不指定,jQuery 將自動(dòng)根據(jù)HTTP包MIME信息返回相應(yīng)類(lèi)型(an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a stringconverters: 轉(zhuǎn)換器,將服務(wù)器端的內(nèi)容根據(jù)指定的dataType轉(zhuǎn)換類(lèi)型,并傳值給success回調(diào)函數(shù)$.ajax({accepts: {mycustomtype: 'application/x-some-custom-type'},// Expect a `mycustomtype` back from serverdataType: 'mycustomtype'// Instructions for how to deserialize a `mycustomtype`converters: {'text mycustomtype': function(result) {// Do Stuffreturn newresult;}},});基于jQueryAjax代碼示例:
<!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title></title> </head> <body><p><input type="button" onclick="XmlSendRequest();" value='Ajax請(qǐng)求' /></p><script type="text/javascript" src="jquery-1.12.4.js"></script><script>function JqSendRequest(){$.ajax({url: "http://c2.com:8000/test/",type: 'GET',dataType: 'text',success: function(data, statusText, xmlHttpRequest){console.log(data);}})}</script> </body> </html>五、跨域AJAX
由于瀏覽器存在同源策略機(jī)制,同源策略阻止從一個(gè)源加載的文檔或腳本獲取或設(shè)置另一個(gè)源加載的文檔的屬性。
特別的:由于同源策略是瀏覽器的限制,所以請(qǐng)求的發(fā)送和響應(yīng)是可以進(jìn)行,只不過(guò)瀏覽器不接受罷了。
瀏覽器同源策略并不是對(duì)所有的請(qǐng)求均制約:
- 制約:?XmlHttpRequest
- 不叼:?img、iframe、script等具有src屬性的標(biāo)簽
跨域,跨域名訪問(wèn),如:http://www.c1.com 域名向 http://www.c2.com域名發(fā)送請(qǐng)求。
1. JSONP實(shí)現(xiàn)跨域請(qǐng)求
JSONP(JSONP - JSON with Padding是JSON的一種“使用模式”),利用script標(biāo)簽的src屬性(瀏覽器允許script標(biāo)簽跨域)
基于JSONP實(shí)現(xiàn)跨域Ajax代碼示例:
<!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title></title> </head> <body><p><input type="button" onclick="Jsonp1();" value='提交'/></p><p><input type="button" onclick="Jsonp2();" value='提交'/></p><script type="text/javascript" src="jquery-1.12.4.js"></script><script>function Jsonp1(){var tag = document.createElement('script');tag.src = "http://c2.com:8000/test/";document.head.appendChild(tag);document.head.removeChild(tag);}function Jsonp2(){$.ajax({url: "http://c2.com:8000/test/",type: 'GET',dataType: 'JSONP',success: function(data, statusText, xmlHttpRequest){console.log(data);}})}</script> </body> </html>2. CORS
隨著技術(shù)的發(fā)展,現(xiàn)在的瀏覽器可以支持主動(dòng)設(shè)置從而允許跨域請(qǐng)求,即:跨域資源共享(CORS,Cross-Origin Resource Sharing),其本質(zhì)是設(shè)置響應(yīng)頭,使得瀏覽器允許跨域請(qǐng)求。
判斷“簡(jiǎn)單請(qǐng)求”或是“非簡(jiǎn)單請(qǐng)求”代碼示例:
條件:1、請(qǐng)求方式:HEAD、GET、POST2、請(qǐng)求頭信息:AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type 對(duì)應(yīng)的值是以下三個(gè)中的任意一個(gè)application/x-www-form-urlencodedmultipart/form-datatext/plain注意:同時(shí)滿足以上兩個(gè)條件時(shí),則是簡(jiǎn)單請(qǐng)求,否則為復(fù)雜請(qǐng)求簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求的區(qū)別?
| 1 2 | ???簡(jiǎn)單請(qǐng)求:一次請(qǐng)求 非簡(jiǎn)單請(qǐng)求:兩次請(qǐng)求,在發(fā)送數(shù)據(jù)之前會(huì)先發(fā)一次請(qǐng)求用于做“預(yù)檢”,只有“預(yù)檢”通過(guò)后才再發(fā)送一次請(qǐng)求用于數(shù)據(jù)傳輸。 |
* 關(guān)于“預(yù)檢”
| 1 2 3 4 5 6 7 | -?請(qǐng)求方式:OPTIONS -?“預(yù)檢”其實(shí)做檢查,檢查如果通過(guò)則允許傳輸數(shù)據(jù),檢查不通過(guò)則不再發(fā)送真正想要發(fā)送的消息 -?如何“預(yù)檢” ?????=> 如果復(fù)雜請(qǐng)求是PUT等請(qǐng)求,則服務(wù)端需要設(shè)置允許某請(qǐng)求,否則“預(yù)檢”不通過(guò) ????????Access-Control-Request-Method ?????=> 如果復(fù)雜請(qǐng)求設(shè)置了請(qǐng)求頭,則服務(wù)端需要設(shè)置允許某請(qǐng)求頭,否則“預(yù)檢”不通過(guò) ????????Access-Control-Request-Headers |
?
基于cors實(shí)現(xiàn)AJAX請(qǐng)求:
a、支持跨域,簡(jiǎn)單請(qǐng)求
服務(wù)器設(shè)置響應(yīng)頭:Access-Control-Allow-Origin = '域名' 或 '*'
<!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title></title> </head> <body><p><input type="submit" onclick="XmlSendRequest();" /></p><p><input type="submit" onclick="JqSendRequest();" /></p><script type="text/javascript" src="jquery-1.12.4.js"></script><script>function XmlSendRequest(){var xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){if(xhr.readyState == 4) {var result = xhr.responseText;console.log(result);}};xhr.open('PUT', "http://c2.com:8000/test/", true);xhr.setRequestHeader('k1', 'v1');xhr.send();}function JqSendRequest(){$.ajax({url: "http://c2.com:8000/test/",type: 'PUT',dataType: 'text',headers: {'k1': 'v1'},success: function(data, statusText, xmlHttpRequest){console.log(data);}})}</script> </body> </html>Tornado代碼:
class MainHandler(tornado.web.RequestHandler):def put(self):self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")self.write('{"status": true, "data": "seven"}')def options(self, *args, **kwargs):self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")self.set_header('Access-Control-Allow-Headers', "k1,k2")self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")self.set_header('Access-Control-Max-Age', 10)c、跨域獲取響應(yīng)頭
默認(rèn)獲取到的所有響應(yīng)頭只有基本信息,如果想要獲取自定義的響應(yīng)頭,則需要再服務(wù)器端設(shè)置Access-Control-Expose-Headers。
HTML:
<!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title></title> </head> <body><p><input type="submit" onclick="XmlSendRequest();" /></p><p><input type="submit" onclick="JqSendRequest();" /></p><script type="text/javascript" src="jquery-1.12.4.js"></script><script>function XmlSendRequest(){var xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){if(xhr.readyState == 4) {var result = xhr.responseText;console.log(result);// 獲取響應(yīng)頭console.log(xhr.getAllResponseHeaders());}};xhr.open('PUT', "http://c2.com:8000/test/", true);xhr.setRequestHeader('k1', 'v1');xhr.send();}function JqSendRequest(){$.ajax({url: "http://c2.com:8000/test/",type: 'PUT',dataType: 'text',headers: {'k1': 'v1'},success: function(data, statusText, xmlHttpRequest){console.log(data);// 獲取響應(yīng)頭console.log(xmlHttpRequest.getAllResponseHeaders());}})}</script> </body> </html>Tornado代碼:
class MainHandler(tornado.web.RequestHandler):def put(self):self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")self.set_header('xxoo', "seven")self.set_header('bili', "daobidao")self.set_header('Access-Control-Expose-Headers', "xxoo,bili")self.write('{"status": true, "data": "seven"}')def options(self, *args, **kwargs):self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")self.set_header('Access-Control-Allow-Headers', "k1,k2")self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")self.set_header('Access-Control-Max-Age', 10)d、跨域傳輸cookie
在跨域請(qǐng)求中,默認(rèn)情況下,HTTP Authentication信息,Cookie頭以及用戶的SSL證書(shū)無(wú)論在預(yù)檢請(qǐng)求中或是在實(shí)際請(qǐng)求都是不會(huì)被發(fā)送。
如果想要發(fā)送:
- 瀏覽器端:XMLHttpRequest的withCredentials為true
- 服務(wù)器端:Access-Control-Allow-Credentials為true
- 注意:服務(wù)器端響應(yīng)的?Access-Control-Allow-Origin 不能是通配符 *
HTML:
<!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title></title> </head> <body><p><input type="submit" onclick="XmlSendRequest();" /></p><p><input type="submit" onclick="JqSendRequest();" /></p><script type="text/javascript" src="jquery-1.12.4.js"></script><script>function XmlSendRequest(){var xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){if(xhr.readyState == 4) {var result = xhr.responseText;console.log(result);}};xhr.withCredentials = true;xhr.open('PUT', "http://c2.com:8000/test/", true);xhr.setRequestHeader('k1', 'v1');xhr.send();}function JqSendRequest(){$.ajax({url: "http://c2.com:8000/test/",type: 'PUT',dataType: 'text',headers: {'k1': 'v1'},xhrFields:{withCredentials: true},success: function(data, statusText, xmlHttpRequest){console.log(data);}})}</script> </body> </html>Tornado:
class MainHandler(tornado.web.RequestHandler):def put(self):self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")self.set_header('Access-Control-Allow-Credentials', "true")self.set_header('xxoo', "seven")self.set_header('bili', "daobidao")self.set_header('Access-Control-Expose-Headers', "xxoo,bili")self.set_cookie('kkkkk', 'vvvvv');self.write('{"status": true, "data": "seven"}')def options(self, *args, **kwargs):self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")self.set_header('Access-Control-Allow-Headers', "k1,k2")self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")self.set_header('Access-Control-Max-Age', 10)?
?
?
總結(jié)
以上是生活随笔為你收集整理的畅游Python 二十二:网页开发技术方案:AJAX的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: uva 340
- 下一篇: 个税起征点上调至5000,用Python