摘要:表單提交在中提供了表單提交的功能,我們可以通過(guò)表單把數(shù)據(jù)從前臺(tái)提交到后臺(tái),通過(guò)設(shè)置事件,可以為按鈕或其它元素同樣可以觸發(fā)表單提交的事件賬號(hào)請(qǐng)輸入賬號(hào)密碼請(qǐng)輸入密碼重置重置提交表示獲取頁(yè)面中所有的表單,返回一個(gè)數(shù)組提交成功通過(guò)表單提交數(shù)據(jù)不需
表單提交
在HTML中提供了表單提交的功能,我們可以通過(guò)表單把數(shù)據(jù)從前臺(tái)提交到后臺(tái),通過(guò)設(shè)置submit事件,可以為按鈕或其它元素同樣可以觸發(fā)表單提交的事件
通過(guò)表單提交數(shù)據(jù)不需要依賴(lài)js引擎,瀏覽器本身就可以實(shí)現(xiàn),但這樣也會(huì)產(chǎn)生一個(gè)問(wèn)題,用戶提交數(shù)據(jù)信息的時(shí)候需要刷新整個(gè)頁(yè)面,這就大大降低了用戶體驗(yàn)
Ajax 什么是AjaxAjax的誕生解決了上述的問(wèn)題,Ajax代表的是:Asynchronous Javascript And XML,也就是異步,javascript和XML,Ajax不是一門(mén)編程語(yǔ)言,而是一種用于創(chuàng)建更好更快交互性更強(qiáng)的web應(yīng)用技術(shù),可以通過(guò)少量的瀏覽器和服務(wù)器之間的數(shù)據(jù)交互實(shí)現(xiàn)頁(yè)面的部分刷新,在使用了Ajax技術(shù)后,用戶的請(qǐng)求數(shù)據(jù)是間接通過(guò)Ajax引擎來(lái)發(fā)出的,而不是直接通過(guò)瀏覽器來(lái)發(fā)出,服務(wù)器返回的數(shù)據(jù)也是傳回到Ajax引擎
Ajax雖然在使用時(shí)的優(yōu)點(diǎn)顯而易見(jiàn),但同時(shí)缺點(diǎn)也是存在的:
對(duì)搜索引擎不友好
用戶無(wú)法使用回退獲得之前的頁(yè)面
我們可以對(duì)比一下傳統(tǒng)的提交方式和使用Ajax技術(shù)的提交方式的不同:
Ajax引擎Ajax的精華部分就是它的Ajax引擎,那么什么是Ajax引擎呢?就是XMLHttpRequest對(duì)象,除了已經(jīng)入土的IE5,其它現(xiàn)代瀏覽器都支持該對(duì)象,同時(shí)它也是一個(gè)JavaScript對(duì)象,它負(fù)責(zé)發(fā)出請(qǐng)求和接收響應(yīng)
在IE5和IE6中Ajax引擎是ActiveXRequest,所以我們可能需要做一下兼容性
使用Ajax 創(chuàng)建Ajax引擎function createRequst() { return window.XMLHttpRequest ? new window.XMLHttpRequest() : new window.ActiveXObject("Microsoft.XMLHTTP"); } console.log(createRequst());//在IE7-中返回的是一個(gè)object對(duì)象
我們?cè)诳刂婆_(tái)中打印出XMLHttpRequest對(duì)象的方法和屬性
我們找?guī)讉€(gè)比較主要的說(shuō)一下,
onloadstart 請(qǐng)求開(kāi)始時(shí)觸發(fā)的事件建立連接onloadend 請(qǐng)求結(jié)束時(shí)觸發(fā)的事件
ontimeout 請(qǐng)求超時(shí)時(shí)觸發(fā)的事件
onreadystatechange 請(qǐng)求狀態(tài)改變時(shí)觸發(fā)的事件
readyState 請(qǐng)求狀態(tài)
status 服務(wù)器返回的狀態(tài)碼
timeout 設(shè)置請(qǐng)求的時(shí)間,當(dāng)請(qǐng)求的時(shí)間超過(guò)我們?cè)O(shè)置的時(shí)間時(shí),自動(dòng)將請(qǐng)求注銷(xiāo)掉
withCredentials 是否要求證書(shū)(例如12306)
responseText 在非XML格式下返回的數(shù)據(jù)
var xhr=createRequst();//封裝的函數(shù) xhr.open("GET","data.php",true); //如果是使用GET方式提交數(shù)據(jù)那么需要在URl后添加?然后把鍵值對(duì)之間以&符號(hào)鏈接拼接在?后面 //如果是使用POST獲取數(shù)據(jù),那么我們要將參數(shù)傳遞到send中,鍵值對(duì)與鍵值對(duì)之間使用&符號(hào)拼接
在建立連接時(shí),我們要調(diào)用open方法,open方法有三個(gè)參數(shù)
open(type,url,isAsync),這幾個(gè)參數(shù)分別代表:
type,請(qǐng)求方式,GET還是POST,當(dāng)然還有其它方式,如DELETE,但不常用,這里不列舉了
url ,請(qǐng)求的服務(wù)器的地址
isAsync ,請(qǐng)求是否異步,默認(rèn)為true,也就是異步請(qǐng)求
GET和POST這里我們需要了解一下同樣是請(qǐng)求后臺(tái)數(shù)據(jù),GET和POST的區(qū)別,如果只是列舉簡(jiǎn)單的區(qū)別:
GET請(qǐng)求是體現(xiàn)在url地址欄中的,安全性比較差,POST是在request body提交的,安全性較高
GET請(qǐng)求的參數(shù)是會(huì)被保存在地址欄中的,而POST不會(huì),也就是說(shuō)在我們使用后退鍵時(shí),使用GET請(qǐng)求會(huì)保存在地址欄中
使用POST的時(shí)候,如果使用后退鍵會(huì)重復(fù)提交,而GET則不會(huì)
POST方式理論上是沒(méi)有大小的限制的,而GET方式由于瀏覽器會(huì)限制地址欄的長(zhǎng)度,一般限制為2K字符以?xún)?nèi),4K大小以?xún)?nèi),超過(guò)部分不予解析
對(duì)于參數(shù)類(lèi)型,GET方式只支持ASCLL編碼格式,而POST則沒(méi)有限制(使用前最好將傳入的數(shù)據(jù)進(jìn)行編碼轉(zhuǎn)換)
但是,在看到一篇大神的文章之后,以上的區(qū)別統(tǒng)統(tǒng)顯的不重要了,我們來(lái)開(kāi)始學(xué)習(xí)怎樣高逼格的說(shuō)明這倆者的不同
我們都知道,無(wú)論是GET還是POST請(qǐng)求,都是建立在HTTP協(xié)議之上的,而HTTP協(xié)議又是建立在TCP協(xié)議之上的,也就是HTTP協(xié)議規(guī)定的數(shù)據(jù)在萬(wàn)維網(wǎng)中傳輸?shù)牡囊?guī)定,那么說(shuō)白了GET和POST只是兩種不同的TCP鏈接,只是由于瀏覽器的規(guī)定設(shè)置導(dǎo)致了有一些差異,在本質(zhì)上并沒(méi)有什么區(qū)別,實(shí)際上真正的差別在于,GET和POST在傳輸數(shù)據(jù)的過(guò)程中,GET會(huì)產(chǎn)生一個(gè)TCP數(shù)據(jù)包,而POST會(huì)產(chǎn)生兩個(gè)數(shù)據(jù)包
瀏覽器在發(fā)送GET請(qǐng)求時(shí)是將http header和data一起發(fā)出,服務(wù)響應(yīng)200,而在發(fā)送POST請(qǐng)求時(shí)。瀏覽器會(huì)先發(fā)送http header,服務(wù)器響應(yīng)100 continue,再發(fā)送data,服務(wù)器響應(yīng)200,也就是說(shuō),GET方式提交數(shù)據(jù)是一次性的,而POST第一次先告訴服務(wù)器我要請(qǐng)求數(shù)據(jù),第二次再將數(shù)據(jù)提交過(guò)去
所以這里由于POST是兩次請(qǐng)求,耗時(shí)會(huì)增加,這也是雅虎優(yōu)化建議中為什么提出,我們盡量將頁(yè)面中使用POST的方式改為GET來(lái)提升響應(yīng)速度,但是,在網(wǎng)絡(luò)性能好的情況下,使用GET和POST的時(shí)間差別幾乎沒(méi)有,在網(wǎng)絡(luò)較差的情況下,兩次打包會(huì)大大提升數(shù)據(jù)的完整性,而且不是所有瀏覽器都是兩次打包的,F(xiàn)irefox就是使用一次打包
至于安全性方面,GET和POST同樣不安全,通過(guò)POST加密的數(shù)據(jù)會(huì)被抓包工具截取,如果有要求使用加密同樣需要通過(guò)加密方式進(jìn)行加密
監(jiān)聽(tīng)狀態(tài)信息繼續(xù)上面的栗子:
xhr.onreadystatechange=function(){ if(xhr.readyState===4){ //判斷請(qǐng)求狀態(tài)是否是已經(jīng)完成 if(xhr.status>=200&&xhr.status<=300||xhr.status===304){ //判斷服務(wù)器是否返回成功200,304 console.log(xhr.responseText); //接收xhr的數(shù)據(jù) } } }
這里有一些需要我們了解的
readyState 請(qǐng)求的狀態(tài)碼
0: 表示請(qǐng)求未初始化,也就是沒(méi)有建立open請(qǐng)求
1: 表示建立open()請(qǐng)求,正在發(fā)送請(qǐng)求
2: 表示請(qǐng)求已經(jīng)接收,open()方法已經(jīng)完成,已經(jīng)收到全部響應(yīng)內(nèi)容
3: 表示請(qǐng)求處理中,正在解析響應(yīng)內(nèi)容
4: 表示請(qǐng)求已經(jīng)完成,響應(yīng)也已經(jīng)就緒,也就是說(shuō)響應(yīng)內(nèi)容已經(jīng)解析完成,可以在客戶端進(jìn)行調(diào)用了
status 服務(wù)器返回的狀態(tài)碼,有幾種常見(jiàn)的類(lèi)型:
以1開(kāi)頭代表請(qǐng)求已經(jīng)接受
以2開(kāi)頭代表請(qǐng)求已經(jīng)成功
200,請(qǐng)求成功
以3開(kāi)頭代表網(wǎng)頁(yè)重定向,常見(jiàn)的幾個(gè):
304,代表瀏覽器緩存可以繼續(xù)使用,服務(wù)器沒(méi)有返回?cái)?shù)據(jù),直接從瀏覽器中獲取數(shù)據(jù)
以4開(kāi)頭代表請(qǐng)求錯(cuò)誤 ,檢查是不是url輸入錯(cuò)誤或者是后臺(tái)人員接口給錯(cuò)了
404,無(wú)法找到指定的資源,也就是url地址錯(cuò)誤
405,請(qǐng)求方法對(duì)請(qǐng)求資源不適用
403,請(qǐng)求不允許
以5開(kāi)頭代表服務(wù)器錯(cuò)誤,需要后臺(tái)人員配合進(jìn)行調(diào)試
如何解決服務(wù)器返回304瀏覽器有默認(rèn)的緩存機(jī)制,在第一次向服務(wù)器請(qǐng)求數(shù)據(jù)的時(shí)候,在發(fā)現(xiàn)頁(yè)面中存在文件請(qǐng)求時(shí)會(huì)發(fā)出請(qǐng)求,并將這些請(qǐng)求緩存在本地,在第二次向服務(wù)器發(fā)送請(qǐng)求的時(shí)候,在請(qǐng)求頭中發(fā)送一個(gè)Last-Modified,它包含了上一次從服務(wù)器獲得數(shù)據(jù)的日期。如果服務(wù)器判斷從這個(gè)日期起服務(wù)器中數(shù)據(jù)沒(méi)有進(jìn)行修改,那么直接返回304的狀態(tài),不再重新發(fā)送數(shù)據(jù),此時(shí)用戶僅僅是獲取了304狀態(tài)碼,不會(huì)再次請(qǐng)求數(shù)據(jù),而是直接從本地讀取緩存
避免服務(wù)器返回304最簡(jiǎn)單的方法就是直接在url地址中添加一個(gè)隨機(jī)數(shù)的時(shí)間戳,例如:/Home/GetMusic?c_time=時(shí)間戳
在前端有個(gè)設(shè)置可以解決讀取緩存的方法,設(shè)置meta標(biāo)簽的屬性
或者設(shè)置Ajax默認(rèn)禁止緩存
var xhr=createRequst();//封裝的函數(shù) xhr.open("GET","data.php",true); xhr.onreadystatechange=()=>{ if(xhr.readyState===4){ if(xhr.status>=200&&xhr.status<=300||xhr.status===304){ console.log(xhr.responseText); } } } xhr.setRequsetHeader("Content-type":"application/x-www-form-urlcoded"); xhr.setRequsetHeader("Canhe-Control","no-cache");//阻止瀏覽器讀取緩存 xhr.send();
如果使用jQuery進(jìn)行開(kāi)發(fā),可以在在jQuery中設(shè)置Ajax的cache屬性,該值默認(rèn)為ture,設(shè)置為false即代表禁止瀏覽器緩存
發(fā)送請(qǐng)求頭在使用POST發(fā)送頁(yè)面的時(shí)候需要注意的是,要發(fā)送請(qǐng)求頭,格式如下:
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //設(shè)置請(qǐng)求頭格式為仿照f(shuō)orm表單提交
在發(fā)送Ajax請(qǐng)求時(shí)默認(rèn)發(fā)送的請(qǐng)求頭格式為文本格式,如果用來(lái)提交表單數(shù)據(jù)會(huì)報(bào)錯(cuò),所以需要我們認(rèn)為的設(shè)置請(qǐng)求頭格式,以上的代碼的作用就是告訴服務(wù)器我們發(fā)送的是form表單格式的數(shù)據(jù)
發(fā)送請(qǐng)求xhr.send();
這里我們注意一個(gè)問(wèn)題,關(guān)于send()的位置問(wèn)題,之前我們一直把send()放在監(jiān)聽(tīng)事件狀態(tài)onreadystatechange之前,這樣寫(xiě)在默認(rèn)的異步狀態(tài)下是沒(méi)有問(wèn)題的,但如果是在同步的狀態(tài)下看,是會(huì)報(bào)錯(cuò)的,這里涉及到了執(zhí)行順序的問(wèn)題,我們是需要先準(zhǔn)備好怎么樣接收數(shù)據(jù),然后才能對(duì)數(shù)據(jù)進(jìn)行接收
JSON數(shù)據(jù)json是一種鍵值對(duì)模式的字符串,其中的鍵和值都是用雙引號(hào)進(jìn)行包裹,由于json的輕量和便于使用,現(xiàn)在大部分公司使用的都是json格式的數(shù)據(jù)
var str={"name":"Tom","age",18}//如果值是數(shù)字的話可以不使用雙引號(hào)包裹
具體關(guān)于json的定義可以參考JSON
JSON的方法在瀏覽器中為我們提供了兩種json數(shù)據(jù)格式轉(zhuǎn)化的方法
JSON.parse(ison),該方法表示將接收到的json數(shù)據(jù)格式轉(zhuǎn)化為對(duì)象格式,需要重點(diǎn)注意的是在使用該方法時(shí),必須是鍵值對(duì)使用雙引號(hào)包裹,所以外層的需要是單引號(hào)
JSON.stringify(object),該方法表示將JavaScript中的對(duì)象轉(zhuǎn)化為json格式的字符串
這里其實(shí)還有一個(gè)方法可以解析json格式的字符串,eval,這個(gè)方法比較特殊,W3C對(duì)它的介紹是,很強(qiáng)大的一個(gè)功能,但是運(yùn)用的很少,這是因?yàn)?b>eval方法本身會(huì)自動(dòng)執(zhí)行字符串中所包含的邏輯語(yǔ)句,所以如果我們使用該方法直接接收沒(méi)有驗(yàn)證過(guò)的返回信息就會(huì)很容易遭到攻擊,例如:
var str={"name":alert("彈出")}; var o=eval(str);
在執(zhí)行上述代碼時(shí)會(huì)自動(dòng)彈出alert提示框,因?yàn)樵谑褂?b>eval時(shí)已經(jīng)執(zhí)行了字符串內(nèi)部的邏輯代碼,所以不推薦使用該方法
JQuery中的Ajax使用在JQuery中對(duì)Ajax方法進(jìn)行了封裝,JQuery的Ajax封裝是非常強(qiáng)大的,在其它框架中也大量借鑒了該方法,下面我們來(lái)看一下在JQuery中是如何使用Ajax的
比較簡(jiǎn)單方法:
$(function(){ $("#btn").on("click",function(){ $.post("02.php",{name:"Tom",age:18},function(data){ console.log(data) },"json") }) }) //相對(duì)應(yīng)的還有GET和getJSON等其它方法,基本套路都一樣
下面的是我們經(jīng)常用到的,同樣也是在其他框架中被參考的方法$.ajax
$.ajax({ type:"get",//設(shè)置請(qǐng)求的方式 url:"02.php",//設(shè)置請(qǐng)求的地址 data:{name:"tom",age:18},//設(shè)置發(fā)送的參數(shù) dataType:"json",//請(qǐng)求的數(shù)據(jù)類(lèi)型,自動(dòng)轉(zhuǎn)化為對(duì)象 async:true,//設(shè)置是否異步,默認(rèn)為true cache:false,//設(shè)置瀏覽器是否緩存該頁(yè)面,默認(rèn)為true timeout:300,//設(shè)置請(qǐng)求超時(shí)時(shí)間 beforeSend:function(xhr){//請(qǐng)求開(kāi)始前回調(diào)該函數(shù) console.log("請(qǐng)求開(kāi)始前"); //return false 如果在請(qǐng)求開(kāi)始前直接return等于阻止了ajax請(qǐng)求 }, success:function(result,status){//請(qǐng)求成功時(shí)回調(diào)該函數(shù),,result代表返回的數(shù)據(jù),status為狀態(tài)描述 console.log("請(qǐng)求成功了"); }, error:function(xhr,status,error){//請(qǐng)求失敗時(shí)回調(diào)該函數(shù),xhr為 XMLHttpRequest對(duì)象,status為錯(cuò)誤信息,error表示捕獲的錯(cuò)誤對(duì)象 console.log("請(qǐng)求失敗,"+xhr.status); } }) //以上只是我們常用的一些方法和參數(shù),JQuery中還封裝了很多其它的方法和參數(shù),包括上面提到的$.get和$.post等方法都是該方法的變種Ajax的封裝
我們簡(jiǎn)單的模擬一下jQuery對(duì)Ajax的封裝
function formatData(data) {//格式化數(shù)據(jù)的方法 var ret = []; for (var key in data) { ret.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key])); //有時(shí)候傳入的可能是漢字,所以需要利用encodeURIComponent轉(zhuǎn)化成編碼格式 //encode方法廢棄了,現(xiàn)在提供的是encodeURLConponent方法 } ret.push(("=" + new Date().getTime())); //添加時(shí)間戳,防止獲取緩存的數(shù)據(jù)(http狀態(tài)碼304) return ret.join("&"); } function createRequst() {//創(chuàng)建Ajax引擎對(duì)象 return XMLHttpRequest() ? new XMLHttpRequest() : new ActiveXObject("Msxml2.XMLHTTP") } function jsonp(option) { //jsonP方法 //判斷用戶傳入的參數(shù) if (!option || !option.url || !option.callback) { console.error("參數(shù)異常"); return; } //如果用戶參數(shù)傳入正確,創(chuàng)建script標(biāo)簽,添加到head標(biāo)簽中 var scriptElement = document.createElement("script"), headElement = document.getElementsByTagName("head")[0]; headElement.appendChild(scriptElement); //注意jsonp創(chuàng)建的函數(shù)是全局函數(shù),為了防止代碼污染,起特定的名字 var fnName = ("jsonp_" + Math.random()).replace(".", ""); option.data[option.callback] = fnName; //給用戶傳入的向后臺(tái)發(fā)送的data數(shù)據(jù)中添加一個(gè)option.callback屬性,并賦值為我們自定義創(chuàng)建的函數(shù)名,讓后臺(tái)接收我們的函數(shù)名,后臺(tái)才能返回給我們數(shù)據(jù) window[fnName] = function (data) { if (option.timeout) {//用戶如果設(shè)置了超時(shí)時(shí)間,在接收到數(shù)據(jù)后將計(jì)時(shí)器清除 window.clearTimeout(scriptElem.timer); } delete window[fnName];//刪除全局函數(shù) headElement.removeChild(scriptElem);//刪除創(chuàng)建的script標(biāo)簽 option.success && option.success(data); } if (option.timeout) {//如果用戶設(shè)置了超時(shí)時(shí)間,設(shè)置計(jì)時(shí)器,在用戶設(shè)置的超時(shí)時(shí)間到達(dá)后如果該函數(shù)執(zhí)行,說(shuō)明超時(shí),那么執(zhí)行其中的代碼 scriptElement.timeout = window.setTimeout(function () { delete global[fnName]; headElem.removeChild(scriptElem); option.fail && option.fail({"message": "請(qǐng)求超時(shí)"}); }, option.timeout) } scriptElem.src = option.url + "?" + formatData(option.data);//執(zhí)行跨域請(qǐng)求,跨域的時(shí)候不需要其它參數(shù),所以data中的數(shù)據(jù)就是callback和它的值 } $.extend({ AjaxSetting: {//設(shè)置用戶默認(rèn)輸入的各項(xiàng)參數(shù) url: "", type: "GET", dataType: "json", async: true, success: null,//成功后執(zhí)行的函數(shù) fail: null,//失敗后執(zhí)行的的函數(shù) contentType: "application/x-www-form-urlencoded;charset=UTF-8"http://模擬表單提交的請(qǐng)求頭 }, ajax: function (url, option) {//在JQuery中使用的兩個(gè)參數(shù),這里仿照J(rèn)Query寫(xiě)法 var context, xhr; if (typeof url === "object") {//判斷url類(lèi)型,如果用戶直接傳入一個(gè)對(duì)象,說(shuō)明沒(méi)有多帶帶傳入U(xiǎn)RL地址,那么我們執(zhí)行下面的代碼 option = url; url = null; } else {//如果用戶多帶帶傳入了url地址,那么我們執(zhí)行下面的代碼 option.url = url; url = undefined; } if (!option || !option.url || !option.success) {//判斷用戶是否輸入option,option中的url和success是我們?cè)O(shè)置為默認(rèn)必須的,所以在用戶傳入時(shí)就進(jìn)行判斷 console.error("參數(shù)傳入異常"); return; //如果用戶傳入的參數(shù)異常,那么我們彈出異常,并且直接返回 } // 通過(guò)JQuery中的extend方法獲取默認(rèn)設(shè)置 $.extend($.AjaxSetting, context); // 通過(guò)JQuery中的extend方法獲取用戶設(shè)置,覆蓋或新增默認(rèn)的設(shè)置 $.extend(option, context); if (context.dataType.toLowerCase() === "jsonp") {//判斷用戶是否要求跨域 jsonp(context);//如果是的話執(zhí)行jsonp的方法 } else {//否則的話執(zhí)行Ajax函數(shù) xhr = createRequst();//通過(guò)createReqyst方法執(zhí)行函數(shù) xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) { var data = context.dataType.toLowerCase() == "json" ? JSON.parse(xhr.responseText) : xhr.responseText; //判斷用戶需求什么格式的數(shù)據(jù),如果是json的數(shù)據(jù),將請(qǐng)求來(lái)的數(shù)據(jù)進(jìn)行轉(zhuǎn)換 context.success && context.success(data, context, xhr); //判斷用戶是否輸入了success方法,如果有的話執(zhí)行success方法,如果我們直接執(zhí)行的 話,由于上面設(shè)置了success為null,用戶如果沒(méi)有設(shè)定會(huì)報(bào)錯(cuò) } } else { context.fail && context.fail({"message": "請(qǐng)求超時(shí)."}) } } if (context.type.toUpperCase() == "GET") { xhr.open("GET", context.url + "?" + formatData(context.data), context.async); //利用formatData方法格式化數(shù)據(jù) xhr.send(); } else { xhr.open("POST", context.url, context.async); xhr.setRequestHeader("contentType", context.contentType) xhr.send(formatData(context.data)); } } } })Ajax輪詢(xún)和長(zhǎng)連接
Ajax輪詢(xún)和長(zhǎng)連接都是為了實(shí)現(xiàn)頁(yè)面的實(shí)時(shí)刷新,但是需要注意,如果在不是必要的情況下盡量不要使用這兩種方法,大量的不間斷的數(shù)據(jù)請(qǐng)求對(duì)前臺(tái)和后臺(tái)都是非常有壓力的,如果要實(shí)現(xiàn)頁(yè)面的實(shí)時(shí)刷新,建議使用WebSocket
Ajax輪詢(xún)客戶端定時(shí)向服務(wù)器發(fā)送Ajax請(qǐng)求,服務(wù)器在返回?cái)?shù)據(jù)后斷開(kāi)連接,輪詢(xún)能夠?qū)崿F(xiàn)頁(yè)面的實(shí)時(shí)刷新,但是缺點(diǎn)也很明顯,定時(shí)的發(fā)送數(shù)據(jù)大部分是沒(méi)有意義的,而且占用額外的服務(wù)器資源
function Ajax(){ setInterval(function(){ var xhr=new XMLHttpRequest(); xhr.open("open","url",true); xhr.onreadystatechange=function(){ if(xhr.readyState===4){ if(xhr.status>=200&&xhr.status<=300||xhr.status==304){ console.log(xhr.responseText) } } }; xhr.setRequestHeader("Content-type","qpplication/x-www-form-urlencoded"); },5000) }
代碼實(shí)際上很簡(jiǎn)單,就是調(diào)用計(jì)時(shí)器,每過(guò)一段時(shí)間向后臺(tái)發(fā)送一次請(qǐng)求
long-polling所以為了能夠使頁(yè)面及時(shí)刷新,并且改善輪詢(xún)存在的弊端,我們一般使用的是長(zhǎng)輪詢(xún)的方法,也就是ling-poling
$(function(){ (function longPolling(){ $.ajax({ url:"01.php", type:"get", datatype:"json", timeout:5000, error:function(xml,status,eror){ //可以選擇報(bào)請(qǐng)求超時(shí)的錯(cuò)誤,不過(guò)一般不這么做 longPolling(); }, success:function(data,status,xhr){ console.log(data); //如果有數(shù)據(jù)返回,那么將數(shù)據(jù)添加到頁(yè)面 longPolling(); } }) })() })
Ajax長(zhǎng)輪詢(xún)需要后臺(tái)寫(xiě)相應(yīng)的代碼來(lái)配合完成,實(shí)際代碼也就是無(wú)論成功或者失敗都再次調(diào)用自身來(lái)向后臺(tái)發(fā)起請(qǐng)求
模板引擎什么是模板引擎,說(shuō)白了就是在字符串中有幾個(gè)變量待定,我們可以用來(lái)配合Ajax請(qǐng)求返回的數(shù)據(jù)來(lái)動(dòng)態(tài)填充頁(yè)面內(nèi)容,例如:
//這里用到的是attTemplate模板引擎
我們可以在寫(xiě)一個(gè)完整的:
Document //導(dǎo)入模板引擎js文件
封裝方法主要是使用了string的方法和正則進(jìn)行匹配,下面寫(xiě)一下大概的封裝
function template(templateStr,data){//傳入兩個(gè)值,templateStr代表模板的字符串,data代表傳入的變量對(duì)象 var reg = /<%=s*([^%>]+S)s*%>/,//定義正則匹配<%= %> result; while(result=reg.exec(templateStr)){//根據(jù)正則的exec方法的屬性如果沒(méi)有符合的返回null來(lái)確定循壞停止的條件 var matchString=result[0],//根據(jù)exec方法返回的是<%= %>這部分的字符串 matchWord=result[1];//根據(jù)exec方法返回的是<%= %>中的字符,也就是我們傳入的data中的鍵 templateStr=templateStr.replace(matchString,data[matchWord]); //調(diào)用字符串的rplace方法,符合的目標(biāo)進(jìn)行替換 } return templateStr; }跨域 什么是跨域
出于安全性的考量,現(xiàn)代所有的瀏覽器都遵循同源策略,同源策略不允許Ajax獲取其它網(wǎng)站的數(shù)據(jù),我們通過(guò)某種方式來(lái)獲取其它網(wǎng)頁(yè)的數(shù)據(jù)的方式就是跨域
同源策略簡(jiǎn)單來(lái)說(shuō)就是在兩個(gè)網(wǎng)頁(yè)域名,端口,協(xié)議任意不同的情況下,A網(wǎng)頁(yè)無(wú)法獲取B網(wǎng)頁(yè)的數(shù)據(jù),舉一個(gè)例子來(lái)說(shuō)明:
http://www.example.com/dir/page.html http://www.example.com/dir2/other.html //同源 http://example.com/dir/other.html //不同源,域名不同 http://v2.www.example.com/dir/other.html //不同源,域名不同 http://www.example.com:81/dir/other.html //不同源,端口不同
注意,同一域名下的不同服務(wù)器獲取數(shù)據(jù)也是跨域,例如兩臺(tái)電腦的IP地址不同,A不能直接獲取B電腦服務(wù)器的數(shù)據(jù)
如果是非同源那么會(huì)受到以下限制:
cookie, localStorage和indexDB無(wú)法讀取
DOM無(wú)法獲取
AJAX請(qǐng)求可以發(fā)送,但是無(wú)法獲取響應(yīng)
具體的內(nèi)容可以參考:同源策略
?
什么是JSONP,很多人會(huì)把jsonp和Ajax搞混,或者認(rèn)為jsonp是Ajax提供的跨域方法,但特別需要注意,這兩者是相互獨(dú)立的,這里引用一段知乎的回答
jsonp的本質(zhì)可以認(rèn)為是由于src屬性不受同源策略的限制,可以獲取其它域的數(shù)據(jù),利用src能夠跨域獲取數(shù)據(jù)的特性來(lái)實(shí)現(xiàn)我們從其它的網(wǎng)站獲取數(shù)據(jù),前提是必須在該網(wǎng)站配合下
實(shí)際在之前的很多操作中我們已經(jīng)使用到了src能夠跨域的這個(gè)特性,例如我們?cè)趇mg中插入一張圖片,可以直接把圖片的地址復(fù)制到src中
?
所以需要注意,src這個(gè)屬性實(shí)際上是等同于發(fā)送了一個(gè)GET形式的Ajax請(qǐng)求,包括href,所以我們?cè)陧?yè)面中盡量不要寫(xiě)空的href和src屬性,可以減小服務(wù)器的壓力
下面我們來(lái)舉一個(gè)jsonP跨域的例子:
在JQ中為我們封裝了跨域的方法,有兩種方式:
1.$.ajax()方法 2.getJson方式window.name
在一個(gè)window的存活周期下,窗口載入的所有頁(yè)面都共享一個(gè)window.name屬性,每個(gè)頁(yè)面都對(duì)它有可讀可寫(xiě)的權(quán)限,即使window.location重載也不會(huì)有變化
window.name的格式為字符串,更多的時(shí)候我們使用json的格式來(lái)進(jìn)行書(shū)寫(xiě),window.name存在字符串的限制,最大的大小為2M
下面我們來(lái)舉一個(gè)栗子:
a.html
b.html
這個(gè)方法和window.name一樣,需要是同一個(gè)頁(yè)面打開(kāi)的窗口
我們直接來(lái)舉一個(gè)栗子:
//數(shù)據(jù)端發(fā)送 //數(shù)據(jù)端接收后臺(tái)轉(zhuǎn)換
這個(gè)方法是實(shí)際工作中最常用的,我們?nèi)绻行枰缬蛘?qǐng)求數(shù)據(jù),一般會(huì)讓后臺(tái)配合請(qǐng)求到數(shù)據(jù)然后在返回給前臺(tái)使用
core這個(gè)后面再說(shuō)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/101816.html
摘要:設(shè)置一個(gè)定時(shí)器,定時(shí)詢(xún)問(wèn)服務(wù)器是否有信息,每次建立連接傳輸數(shù)據(jù)之后,鏈接會(huì)關(guān)閉。通過(guò)調(diào)用此程序提供的套接口接口與服務(wù)器端的套接口進(jìn)行通信。 本文同步自我的博客園:http://hustskyking.cnblogs.com P.S: 各個(gè)平臺(tái)中就 segmentFault 寫(xiě)博客體驗(yàn)最好了! web通信,一個(gè)特別大的topic,涉及面也是很廣的。因最近學(xué)習(xí)了 javascript 中...
摘要:由兩部分組成回調(diào)函數(shù)和數(shù)據(jù)。回調(diào)函數(shù)是當(dāng)響應(yīng)到來(lái)時(shí)應(yīng)該在頁(yè)面中調(diào)用的函數(shù),回調(diào)函數(shù)的名字一般是在請(qǐng)求中指定的。下面是以個(gè)的例子回調(diào)函數(shù)的名字就是是通過(guò)動(dòng)態(tài)的元素來(lái)使用的,使用時(shí)可以為屬性指定一個(gè)跨域。是為與其他傳遞消息的很相似。 圖像Ping技術(shù) 根據(jù)一個(gè)網(wǎng)頁(yè)可以從任何網(wǎng)頁(yè)中加載圖像而不用擔(dān)心使用跨域的原理, 我們可以動(dòng)態(tài)的創(chuàng)建圖像, 使用他們的onload和onerror事件處理程序...
摘要:希望幫助更多的前端愛(ài)好者學(xué)習(xí)。前端開(kāi)發(fā)者指南作者科迪林黎,由前端大師傾情贊助。翻譯最佳實(shí)踐譯者張捷滬江前端開(kāi)發(fā)工程師當(dāng)你問(wèn)起有關(guān)與時(shí),老司機(jī)們首先就會(huì)告訴你其實(shí)是個(gè)沒(méi)有網(wǎng)絡(luò)請(qǐng)求功能的庫(kù)。 前端基礎(chǔ)面試題(JS部分) 前端基礎(chǔ)面試題(JS部分) 學(xué)習(xí) React.js 比你想象的要簡(jiǎn)單 原文地址:Learning React.js is easier than you think 原文作...
摘要:提供一系列新事件,在中我們一般只應(yīng)用,然后檢查狀態(tài)值再?zèng)Q定下一步操作,提供回調(diào)函數(shù)簡(jiǎn)化了這一步驟,在接收完數(shù)據(jù)的時(shí)候即可觸發(fā)。的事件的回調(diào)函數(shù)的事件參數(shù)有兩個(gè)重要屬性和,用來(lái)計(jì)算百分值。不具備對(duì)象及其事件方法。 AJAX(Asynchronous Javascript And XML:異步JavaScript和XML) AJAX 已經(jīng)是老生常談的話題了,它最早起源于1997年,由 Mi...
閱讀 2503·2021-11-24 10:29
閱讀 2644·2021-09-24 09:48
閱讀 5751·2021-09-22 15:56
閱讀 3163·2021-09-06 15:00
閱讀 2677·2019-08-30 15:54
閱讀 749·2019-08-30 13:48
閱讀 2927·2019-08-30 11:17
閱讀 3430·2019-08-29 11:20