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