目錄javascript
對於Ajax如今相信你們已經不會陌生了,不管是原生的XMLHttpRequest方式發送仍是經過jQuery框架中提供的$.ajax方式。可是從實際工做角度來講並非全部的公司都喜歡採用上面兩種方式進行請求的發送。php
其緣由在於:html
(1)原生的方式過於繁瑣,而且大量重複代碼。java
(2)jQuery的方式雖然方便,但必須引入jQuery框架,jquery
而框架中不是全部的內容都能用到,這就形成了大量無用代碼的堆積。佔用資源web
所以咱們自行封裝知足於咱們需求的Ajax框架就勢在必行,這節課咱們就一塊兒來封裝一個屬於咱們本身的Ajax框架。ajax
在此以前爲了能更好的的理解今天的內容,讓咱們先一塊兒複習一下前兩種方式:json
(1)原生Ajax請求後端
(2)jQuery中的$.ajax()請求跨域
1)原生ajax請求
var xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject("");
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
console.log(JSON.parse(xhr.responseText));
}else{
console.log(xhr.statusText);
}
}
}
xhr.open('請求類型get/post','請求地址url',true);
xhr.setRequestHeader('Content-Type','application/json');
xhr.send(若是post請求則在這些formData);
2), jQuery中的$,ajax()請求
<script src='xxx/jquery1.12.3.min.js'></script>
<script>
//…
$.ajax({
type:'get|post',
url:'http://xxxx/xxx.php',
dataType:'json',
data:'若是是post請求則必須寫',
success:function(jsonData){
console.log(jsonData);
},
error:function(err){
console.log(err);
}
});
</script>
好了,讓咱們暫且先複習到這裏。若是你對上面的內容可以掌握的很是熟練的話,就可以在咱們剛纔書寫的過程當中感到一絲絲的不舒服的地方。
那就是jq的方式簡便快捷又好用,相比之下原生的寫法簡直麻煩。
而這,正是咱們要自行封裝Ajax的緣由:
由於jq的方式簡便快捷,可是jq框架卻過於龐大。
因此咱們要自行編寫一個屬於咱們本身的,只用於處理Ajax的簡便框架。
2,封裝ajax
實際上自封裝Ajax請求文件,就是將原生Ajax的請求步驟抽象爲一個函數,並單獨生成一個js文件保存,當用到的時候直接引入這個文件的過程。
很顯然這是個一次性的工做,封裝完畢以後咱們之後直接拿來直接使用便可。
封裝Ajax大體分紅下列幾個步驟:
(1)提供建立xhr對象的兼容性函數。
(2)提供發送請求的對外接口
(3)設計並約定對外接口的參數規格
(4)實現對外接口中參數處理
(5)實現對外接口中響應處理
(6)實現對外接口中發送處理
(7)設置命名空間,避免全局變量污染。
(1)提供建立xhr對象的兼容性函數
a.讓咱們先建立一個js文件,並命名爲EncapsulationAjax.js。(這就是咱們的框架文件)
b.在這個文件內部先聲明一個無參函數,命名爲createXhr。
function createXhr(){}
c.這個函數是爲了得到xhr兼容性對象才書寫的,所以在裏面書寫兼容性代碼
function createXhr(){
return window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject(‘’);
}
(2)提供發送請求的對外接口
a.聲明對外發送請求的接口,命名爲ajax。
function ajax(){}
b.爲接口設置一個json格式的參數用於接收相關數據,命名爲jsonObj
function ajax(jsonObj){}
(3).設計並約定接口的參數規格
(4)實現對外接口中參數處理
a.對外接口中建立xhr對象
function ajax(jsonObj){
var xhr = createXhr();
}
b.根據請求方式設置參數。
function ajax(jsonObj){
var xhr = createXhr();
}
(5)實現對外接口中響應處理
a.根據請求方式設置回調函數。
function ajax(jsonObj){
//…
if(jsonObj.async === true){
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
if(xhr.status == 200){
jsonObj.success(JSON.parse(xhr.responseText));
}else{
jsonObj.error(xhr.statusText);
}
}
}
}
}
(6)實現對外接口中發送處理
a. 調用open+send函數。
function ajax(jsonObj){
//…
xhr.open(obj.method,obj.url,obj.async);
if(obj.method === "post"){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(obj.data);
}else{
xhr.send();
}
}
(7)設置命名空間,避免全局變量污染
由於咱們所編寫的js文件中存在大量全局變量,而這樣的全局變量會對其餘文件中的內容形成不可預估的影響。在js中函數能夠劃分做用域,所以咱們採用自執行函數將總體包裹,避免了內部建立的變量對全局變量形成的影響。
可是這樣一來帶來的一個重要問題就是,內部建立的函數對外也變成了不可見狀態,所以咱們能夠藉助window對象來將內部建立的對外接口設置爲「可見狀態」.
(function(){
//…
funtion ajax(){
//…
}
window.ajax = ajax;
}());
OK,到此爲止一個名爲EncapsulationAjax的框架封裝完成了。
這個框架歸屬於咱們本身,而且具備咱們所期待的一系列特色:
a.輕量級,寥寥幾十行代碼
b.兼容性,可以處理IE中不少版本的Ajax請求
c.便捷性,參數都是本身規定的,用着方便
d.擴展性,若是還須要更多的功能直接添加進去便可,不會有任何內容衝突。
那麼既然已經編寫了一個屬於咱們本身的工具,就讓咱們來看看在實際工做中他的表現吧!
3,案例:使用自封裝ajax
要求:
(1) html文檔結構以下:
(2)發送Ajax使用EncapsulationAjax.js提供的方法實現。
(3)php文檔內容以下:
if($_POST){
echo json_encode(array('info'=>$_POST, 'desc'=>'post'));
}else{
echo json_encode(array('info'=>$_GET, 'desc'=>'get'));
}
Post請求返回結果:
Get請求返回結果
4,案例:動態加載瀑布流
要求:
(1)總體html結構和js部分都和以前的代碼沒有衝突和區別
只是須要將【本來的模擬數據】變成【真正的Ajax請求來的數據】。
(2)對於獲取數據而言,採用get請求。
(3)最後須要將整個處理瀑布流加載過程的代碼,放置到success中執行
(4)php後臺文件中只須要將圖片的路徑地址構建,並返回便可。
$imgArr = [‘http://127.0.0.1/waterfall/i1.jpg’,‘http://127.0.0.1/waterfall/i2.jpg’,…];
$finalArr = array('desc'=>'success', 'imgArr'=>$imgArr);
echo json_encode($finalArr);
ajax({
method:'get',
url:'waterfall.php',
async:true,
success:function(data){
//…構建瀑布流的代碼
},
error:function(error){
console.log(error);
}
});
5.跨域
(1)瀏覽器同源政策
(2)Ajax跨域
(3)JSONP跨域方案(get請求)
(1).瀏覽器同源政策
(1)瀏覽器同源政策
起源:1995年,同源政策由Netscape公司引入瀏覽器。
含義:最初的目的是某頁面所設置的cookie,只能由其「同源」頁面打開。
說明:「同源」:協議相同、域名相同、端口相同
例子:http://www.frank.com/sxt/page.html這個網址
協議是:http://
域名是:www.frank.com
端口是:80(默認端口能夠省略)。
它的同源狀況以下:
http://www.frank.com/sxt2/other.html:同源
http://frank.com/sxt/other.html:不一樣源(域名不一樣)
http://v3.www.frank.com/sxt/other.html:不一樣源(域名不一樣)
http://www.frank.com:81/dir/other.html:不一樣源(端口不一樣)
目的:同源政策的目的,是爲了保證用戶信息的安全,防止惡意的網站竊取數據。
限制:隨着互聯網的發展,"同源政策"愈來愈嚴格。
目前,若是非同源,共有三種行爲受到限制:
(1)Cookie、LocalStorage 和 IndexDB 沒法讀取。
(2)DOM 沒法得到。
(3)AJAX 請求不能發送。
補充:凡事都有利有弊,儘管限制是有必要的,
但在有些狀況下合理的用途也會因「同源政策」而受到影響。
所以咱們將要爲你們介紹的一些規避上述限制的手段,就是【跨域】的由來。
(2)Ajax跨域
描述:Ajax跨域指的是將Ajax請求進行跨域處理,而不是說在Ajax中提供了跨域的方法。
由來:同源政策中明確規定Ajax請求只能發給同源的網址,不然就會發生跨域報錯。
解法:除了設置代理以外頁面中有三種常見的解決跨域的手段,
而根據咱們所掌握的內容來考慮,咱們只學習最多見的一種叫作JSONP的方法。
其他另外兩種分別叫作webSocket和CORS。
(3)JSONP跨域方式
描述:JSONP是服務器與客戶端跨源通訊的最經常使用方法。
最大特色就是簡單適用,老式瀏覽器所有支持,對服務器改造很是小。
本質:實際上利用了script標籤引入js文件,並解析執行的原理。
語法:
(1)在html中插入script標籤,並利用script標籤發起跨源請求
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = '跨源url地址?【先後端約定回調關鍵詞】=【回調函數名】';
document.body.appendChild(script);
(2)在服務器對應php文件中經過拼接字符串,模擬函數調用。
並將要返回數據經過回調函數參數返回。
$response = $_GET['先後端約定回調關鍵詞'];
echo $response."(".json_encode(要返回數據).")";
(3)在html頁面中,顯式寫出回調函數。這樣當跨源請求完成後對應回調函數會自動執行。
function 回調函數名(data) {
console.log(data);
};
優勢:
(1)因爲使用script腳本做爲請求,所以實際上請求和傳統的引入js腳本沒有任何區別。
(2)而在返回的數據中咱們也儘可能模擬出了js調用函數的語法,
所以只要在頁面中聲明瞭回調函數就會自動被調用。
(3)再者做爲參數的【服務器端】的JSON數據,在js中是被直接識別爲對象,
所以在回調函數中也避免了使用JSON.parse的步驟。