概述
??什么是ajax
??它是一種用于創(chuàng)建快速動態(tài)網(wǎng)頁的技術(shù)吭从,通過后臺與服務(wù)器進(jìn)行少量數(shù)據(jù)交換(請求后端數(shù)據(jù)),ajax可以使網(wǎng)頁實現(xiàn)異步更新胞此,即在不更新整個網(wǎng)頁的情況下臣咖,進(jìn)行部分網(wǎng)頁更新,減少用戶的等待時間漱牵,加快響應(yīng)夺蛇。
??AJAX = 異步 JavaScript 和 XML。AJAX 是一種用于創(chuàng)建快速動態(tài)網(wǎng)頁的技術(shù)酣胀。
??XmlHttpRequest對象
??XMLHttpRequest 對象所有的是ajax的基礎(chǔ)刁赦,XMLHttpRequest 用于在后臺與服務(wù)器的數(shù)據(jù)交互 目前所有的瀏覽器都支持XMLHttpRequest娶聘。
??1.XmlHttpRequest對象的主要方法
a. void open(String method,String url,Boolen async) ------------ 用于創(chuàng)建請求
參數(shù):
method: 請求方式(字符串類型),如:POST甚脉、GET丸升、DELETE...
url: 要請求的地址(字符串類型)
async: 是否異步(布爾類型),一般填true
b. void send(String body) -------------------------------------- 用于發(fā)送請求
參數(shù):
body: 要發(fā)送的數(shù)據(jù)(字符串類型)
c. void setRequestHeader(String header,String value)-------------用于設(shè)置請求頭
參數(shù):
header: 請求頭的key(字符串類型)
vlaue: 請求頭的value(字符串類型)
d. String getAllResponseHeaders() -------------------------------獲取所有響應(yīng)頭
返回值:
響應(yīng)頭數(shù)據(jù)(字符串類型)
e. String getResponseHeader(String header)-----------------------獲取響應(yīng)頭中指定header的值
參數(shù):
header: 響應(yīng)頭的key(字符串類型)
返回值:
響應(yīng)頭中指定的header對應(yīng)的值
f. void abort()-------------------------------------------------終止請求
??2.XmlHttpRequest對象的主要屬性
a. Number readyState
狀態(tài)值(整數(shù))
詳細(xì):
0-未初始化牺氨,尚未調(diào)用open()方法狡耻;
1-啟動,調(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的值改變時自動觸發(fā)執(zhí)行其對應(yīng)的函數(shù)(回調(diào)函數(shù))
c. String responseText
服務(wù)器返回的數(shù)據(jù)(字符串類型)
d. XmlDocument responseXML
服務(wù)器返回的數(shù)據(jù)(Xml對象)
e. Number states
狀態(tài)碼(整數(shù))庄撮,如:200背捌、404...
f. String statesText
狀態(tài)文本(字符串),如:OK洞斯、NotFound...
??跨域
??JavaScript出于安全方面的考慮毡庆,不允許跨域調(diào)用其他頁面的對象。那什么是跨域呢烙如,簡單地理解就是因為JavaScript同源策略的限制么抗,a.com域名下的js無法操作b.com或是c.a.com域名下的對象。
??當(dāng)協(xié)議亚铁、子域名蝇刀、主域名、端口號中任意一個不相同時徘溢,都算作不同域吞琐。不同域之間相互請求資源,就算作“跨域”
??跨域并不是請求發(fā)不出去然爆,請求能發(fā)出去站粟,服務(wù)端能收到請求并正常返回結(jié)果,只是結(jié)果被瀏覽器攔截了曾雕。
構(gòu)建原生ajax
注意:
??XmlHttpRequest支持:
????IE7+, Firefox, Chrome, Opera, etc.
????IE6, IE5不支持XmlHttpRequest奴烙,所以使用ActiveXObject("Microsoft.XMLHTTP")對象實現(xiàn)。
??第一步:獲得XMLHttpRequest對象
??第二步:設(shè)置狀態(tài)監(jiān)聽函數(shù)
??第三步:open一個連接,true是異步請求
??第四部:send一個請求切诀,可以發(fā)送一個對象和字符串揩环,不需要傳遞數(shù)據(jù)發(fā)送null
??第五步:在監(jiān)聽函數(shù)中,判斷readyState=4&&status=200表示請求成功
??第六步:使用responseText幅虑、responseXML接受響應(yīng)數(shù)據(jù)检盼,并使用原生JS操作DOM進(jìn)行顯示
var xhr = null;
if(XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
// 定義回調(diào)函數(shù)
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 已經(jīng)接收到全部響應(yīng)數(shù)據(jù),執(zhí)行以下操作
var data = xhr.responseText;
alert(data);
}
};
// 指定連接方式和地址----文件方式//默認(rèn)異步請求 true
//xhr.open('get', "/test", true);
xhr.open('POST', "/test", true);
// 設(shè)置請求頭
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
// 發(fā)送請求
//xhr.send();
xhr.send('n1=1;n2=2;');
??平時我們用的最多的還是jQuery的ajax翘单,jQuery其實就是一個JavaScript的類庫,其將復(fù)雜的功能做了上層封裝蹦渣,使得開發(fā)者可以在其基礎(chǔ)上寫更少的代碼實現(xiàn)更多的功能(想要了解)哄芜。
??其他,類似vue的axios是通過promise實現(xiàn)對ajax技術(shù)的一種封裝柬唯。就像jQuery實現(xiàn)ajax封裝一樣认臊。(了解axios)
ajax的跨域請求
??瀏覽器同源策略并不是對所有的請求均制約:
????制約: XmlHttpRequest
????無效: img、iframe锄奢、script等具有src屬性的標(biāo)簽
??那么如有解決跨域請求的問題呢失晴?下面提供了幾種方法實現(xiàn)跨域請求。
??1.JSONP
??利用 <script> 元素的這個開放策略拘央,網(wǎng)頁可以得到從其他來源動態(tài)產(chǎn)生的 JSON 數(shù)據(jù)涂屁。JSONP請求一定需要對方的服務(wù)器做支持才可以。
??JSONP優(yōu)點是兼容性好灰伟,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題拆又。缺點是僅支持get方法具有局限性。
??(1)JSONP的流程
??聲明一個回調(diào)函數(shù)栏账,其函數(shù)名(如fn)當(dāng)做參數(shù)值帖族,要傳遞給跨域請求數(shù)據(jù)的服務(wù)器,函數(shù)形參為要獲取目標(biāo)數(shù)據(jù)(服務(wù)器返回的data)挡爵。
??創(chuàng)建一個<script>標(biāo)簽竖般,把那個跨域的API數(shù)據(jù)接口地址,賦值給script的src,還要在這個地址中向服務(wù)器傳遞該函數(shù)名(可以通過問號傳參:?callback=fn)茶鹃。
??服務(wù)器接收到請求后涣雕,需要進(jìn)行特殊的處理:把傳遞進(jìn)來的函數(shù)名和它需要給你的數(shù)據(jù)拼接成一個字符串,例如:傳遞進(jìn)去的函數(shù)名是fn,它準(zhǔn)備好的數(shù)據(jù)是fn([{"name":"jianshu"}])闭翩。
??最后服務(wù)器把準(zhǔn)備的數(shù)據(jù)通過HTTP協(xié)議返回給客戶端胞谭,客戶端再調(diào)用執(zhí)行之前聲明的回調(diào)函數(shù)(fn),對返回的數(shù)據(jù)進(jìn)行操作男杈。
<script type="text/javascript">
function fn(data) {
alert(data.msg);
}
</script>
<script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=fn"></script>
??其中 fn 是客戶端注冊的回調(diào)的函數(shù),目的獲取跨域服務(wù)器上的json數(shù)據(jù)后丈屹,對數(shù)據(jù)進(jìn)行在處理。
??最后服務(wù)器返回給客戶端數(shù)據(jù)的格式為:
fn({ msg:'this is json data'})
??(2)jQuery的jsonp請求
emsp;?JSONP都是GET和異步請求的,不存在其他的請求方式和同步請求旺垒,且jQuery默認(rèn)就會給JSONP的請求清除緩存彩库。
$.ajax({
url:"http://crossdomain.com/jsonServerResponse",
dataType:"jsonp",
type:"get",//可以省略
jsonpCallback:"fn",//->自定義傳遞給服務(wù)器的函數(shù)名,而不是使用jQuery自動生成的,可省略
jsonp:"jsonp",//->把傳遞函數(shù)名的那個形參callback變?yōu)閖sonp,可省略
success:function (data){
console.log(data);}
});
??2.CORS
??1.CORS原理
??整個CORS通信過程睁冬,都是瀏覽器自動完成奸例,不需要用戶參與。對于開發(fā)者來說虑粥,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發(fā)現(xiàn)AJAX請求跨源鳞仙,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求笔时,但用戶不會有感覺棍好。因此,實現(xiàn)CORS通信的關(guān)鍵是服務(wù)器允耿。只要服務(wù)器實現(xiàn)了CORS接口借笙,就可以跨源通信。
??2.CORS優(yōu)缺點
??CORS要求瀏覽器(>IE10)和服務(wù)器的同時支持较锡,是跨域的根本解決方法业稼,由瀏覽器自動完成。
??優(yōu)點在于功能更加強大支持各種HTTP Method蚂蕴,缺點是兼容性不如JSONP盼忌。
??只需要在服務(wù)器端做一些小小的改造即可:
header("Access-Control-Allow-Origin:*");
header("Access-Control-Allow-Methods:POST,GET");
??例如:網(wǎng)站http://localhost:63342/ 頁面要請求http://localhost:3000/users/userlist 頁面,userlist頁面返回json字符串格{name: 'Mr.Cao', gender: 'male', career: 'IT Education'}
??JAVA后臺配置
????JAVA后臺配置只需要遵循如下步驟即可:
????第一步:獲取依賴jar包下載 cors-filter-1.7.jar, java-property-utils-1.9.jar 這兩個庫文件放到lib目錄下掂墓。(放到對應(yīng)項目的webcontent/WEB-INF/lib/下)
????第二步:如果項目用了Maven構(gòu)建的,請?zhí)砑尤缦乱蕾嚨絧om.xml中:
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>[ version ]</version>
</dependency>
??在響應(yīng)頭上添加Access-Control-Allow-Origin屬性谦纱,指定同源策略的地址。同源策略默認(rèn)地址是網(wǎng)頁的本身君编。只要瀏覽器檢測到響應(yīng)頭帶上了CORS跨嘉,并且允許的源包括了本網(wǎng)站,那么就不會攔截請求響應(yīng)吃嘿。
??3.使用HTML5中新引進(jìn)的window.postMessage方法來跨域傳送數(shù)據(jù)
??window.postMessage(message,targetOrigin) 方法是html5新引進(jìn)的特性祠乃,可以使用它來向其它的window對象發(fā)送消息,無論這個window對象是屬于同源或不同源兑燥,目前IE8+亮瓷、FireFox、Chrome降瞳、Opera等瀏覽器都已經(jīng)支持window.postMessage方法嘱支。
??調(diào)用postMessage方法的window對象是指要接收消息的那一個window對象蚓胸,該方法的第一個參數(shù)message為要發(fā)送的消息,類型只能為字符串除师;第二個參數(shù)targetOrigin用來限定接收消息的那個window對象所在的域沛膳,如果不想限定域,可以使用通配符 * 汛聚。
??需要接收消息的window對象锹安,可是通過監(jiān)聽自身的message事件來獲取傳過來的消息,消息內(nèi)容儲存在該事件對象的data屬性中倚舀。
??上面所說的向其他window對象發(fā)送消息叹哭,其實就是指一個頁面有幾個框架的那種情況,因為每一個框架都有一個window對象痕貌。在討論第二種方法的時候风罩,我們說過,不同域的框架間是可以獲取到對方的window對象的芯侥,而且也可以使用window.postMessage這個方法。下面看一個簡單的示例乳讥,有兩個頁面
//發(fā)送信息頁面 http://localhost:63342/index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>跨域請求</title>
</head>
<body>
<iframe src="http://localhost:3000/users/reg" id="frm"></iframe>
<input type="button" value="OK" onclick="run()">
</body>
</html>
<script>
function run(){
var frm=document.getElementById("frm");
frm.contentWindow.postMessage("跨域請求信息","http://localhost:3000");
}
</script>
//接收信息頁面 http://localhost:3000/message.html
window.addEventListener("message",function(e){ //通過監(jiān)聽message事件柱查,可以監(jiān)聽對方發(fā)送的消息。
console.log(e.data);
},false);