Ajax基礎知識

作者:日期:2018-03-18 18:23:58 點擊:1007

AJAX基礎知識

什么是AJAX?
async javascript and xml,異步的JS和XML

xml:可擴展的標記語言

作用是用來存儲數據的(通過自己擴展的標記名稱清晰的展示出數據結構)

ajax之所以稱為異步的js和xml,主要原因是:當初最開始用ajax實現客戶端和服務器端數據通信的時候,傳輸的數據格式一般都是xml格式的數據,我們我們把它稱之為異步js和xml(現在一般都是基于JSON格式來進行數據傳輸的)

<?xml version="1.0" encoding="UTF-8"?><root>     <student>         <name>張三</name>         <age>25</age>         <score>             <english>90</english>             <math>100</math>             <chinese>98</chinese>         </score>     </student>     <student>         <name>李四</name>         <age>24</age>         <score>             <english>80</english>             <math>90</math>             <chinese>100</chinese>         </score>     </student></root>

異步的JS

這里的異步不是說ajax只能基于異步進行請求(雖然建議都是使用異步編程),這里的異步特指的是 “局部刷新”

局部刷新 VS 全局刷新

在非完全前后端分離項目中,前端開發只需要完成頁面的制作,并且把一些基礎的人機交互效果使用js完成即可,頁面中需要動態呈現內容的部分,都是交給后臺開發工程師做數據綁定和基于服務器進行渲染的(服務器端渲染)

[優勢]
1、動態展示的數據在頁面的原代碼中可以看見,有利于SEO優化推廣(有利于搜索引擎的收錄和抓取)
2、從服務器端獲取的結果就已經是最后要呈現的結果了,不需要客戶端做額外的事情,所以頁面加載速度快(前提是服務器端處理的速度夠快,能夠處理過來),所以類似于京東、淘寶這些網站,首屏數據一般都是經由服務器端渲染的

[弊端]
1、如果頁面中存在需要實時更新的數據,每一次想要展示最新的數據,頁面都要重新的刷新一次,這樣肯定不行
2、都交給服務器端做數據渲染,服務器端的壓力太大,如果服務器處理不過來,頁面呈現的速度更慢(所以京東淘寶這類網站,除了首屏是服務器端渲染的,其它屏一般都是客戶端做數據渲染綁定)
3、這種模式不利于開發(開發效率低)

目前市場上大部分項目都是前后端完全分離的項目(也有非完全前后端分離的)

前后端完全分離的項目,頁面中需要動態綁定的數據是交給客戶端完成渲染的
1、向服務器端發送AJAX請求
2、把從服務器端獲取的數據解析處理,拼接成為我們需要展示的HTML字符串
3、把拼接好的字符串替換頁面中某一部分的內容(局部刷新),頁面整體不需要重新加載,局部渲染即可

[優勢]
1、我們可以根據需求,任意修改頁面中某一部分的內容(例如實時刷新),整體頁面不刷新,性能好,體驗好(所有表單驗證、需要實時刷新的等需求都要基于AJAX實現)

2、有利于開發,提高開發的效率
1)前后端的完全分離,后臺不需要考慮前端如何實現,前端也不需要考慮后臺用什么技術,真正意義上實現了技術的劃分
2)可以同時進行開發:項目開發開始,首先制定前后端數據交互的接口文檔(文檔中包含了,調取哪個接口或者哪些數據等協議規范),后臺把接口先寫好(目前很多公司也需要前端自己拿NODE來模擬這些接口),客戶端按照接口調取即可,后臺再次去實現接口功能即可

[弊端]
1、不利于SEO優化:第一次從服務器端獲取的內容不包含需要動態綁定的數據,所以頁面的源代碼中沒有這些內容,不利于SEO收錄,后期通過JS添加到頁面中的內容,并不會寫在頁面的源代碼中(是源代碼不是頁面結構)
2、交由客戶端渲染,首先需要把頁面呈現,然后再通過JS的異步AJAX請求獲取數據,然后數據綁定,瀏覽器在把動態增加的部分重新渲染,無形中浪費了一些時間,沒有服務器端渲染頁面呈現速度快

基于原生JS實現AJAX

//=>創建一個AJAX對象
let xhr=new XMLHttpRequest();
//=>不兼容IE6及更低版本瀏覽器(IE6:ActiveXObject)
//=>打開請求地址(可以理解為一些基礎配置,但是并沒有發送請求呢)
xhr.open([method],[url],[async],[user name],[user password]);
//=>監聽AJAX狀態改變,獲取響應
信息(獲取響應頭信息、獲取響應主體信息)
xhr.onreadystatechange=()=>{    
   if(xhr.readyState===4 && xhr.status===200){        
       let result=xhr.responseText;//=>獲取響應主體中的內容    } };
//=>發送AJAX請求(括號中傳遞的內容就是請求主體的內容)
xhr.send(null);

分析第二步中的細節點

xhr.open([method],[url],[async],[user name],[user password])


[AJAX請求方式]
1、GET系列的請求(獲取)

  • get

  • delete:從服務器上刪除某些資源文件

  • head:只想獲取服務器返回的響應頭信息(響應主體內容不需要獲取)

2、POST系列請求(推送)

  • post

  • put:向服務器中增加指定的資源文件

不管哪一種請求方式,客戶端都可以把信息傳遞給服務器,服務器也可以把信息返回給客戶端,只是GET系列一般以獲取為主(給的少,拿回來的多),而POST系列一般以推送為主(給的多,拿回來的少)
1)我們想獲取一些動態展示的信息,一般使用GET請求,因為只需要向服務器端發送請求,告訴服務器端我們想要什么,服務器端就會把需要的數據返回
2)在實現注冊功能的時候,我們需要把客戶輸入的信息發送給服務器進行存儲,服務器一般返回成功還是失敗等狀態,此時我們一般都是基于POST請求完成

GET系列請求和POST系列請求,在項目實戰中存在很多的區別
1、GET請求傳遞給服務器的內容一般沒有POST請求傳遞給服務器的內容多
原因:GET請求傳遞給服務器內容一般都是基于url地址問號傳遞參數來實現的,而POST請求一般都是基于設置請求主體來實現的。
各瀏覽器都有自己的關于URL最大長度的限制(谷歌:8KB、火狐:7KB、IE:2KB…)超過限制長度的部分,瀏覽器會自動截取掉,導致傳遞給服務器的數據缺失。
理論上POST請求通過請求主體傳遞是沒有大小限制的,真實項目中為了保證傳輸的速率,我們也會限制大小(例如:上傳的資料或者圖片我們會做大小的限制)

2、GET請求很容易出現緩存(這個緩存不可控:一般我們都不需要),而POST不會出現緩存(除非自己做特殊處理);
原因:GET是通過URL問號傳參傳遞給服務器信息,而POST是設置請求主體;
設置請求主體不會出現緩存,但是URL傳遞參數就會了。
```javascript
//=>每個一分鐘從新請求服務器端最新的數據,然后展示在頁面中(頁面中某些數據實時刷新)
setTimeout(()=>{
$.ajax({
url:’getList?lx=news’,

success:result=>{
//=>第一次請求數據回來,間隔一分鐘后,瀏覽器又發送一次請求,但是新發送的請求,不管是地址還是傳遞的參數都和第一次一樣,瀏覽器很有可能會把上一次數據獲取,而不是獲取最新的數據
}
});
},60000);

//=>解決方案:每一次重新請求的時候,在URL的末尾追加一個隨機數,保證每一次請求的地址不完全一致,就可以避免是從緩存中讀取的數據
setTimeout(()=>{
$.ajax({
url:’getList?lx=news&_=’+Math.random(),

success:result=>{}
});
},60000);


3、GET請求沒有POST請求安全(POST也并不是十分安全,只是相對安全) 原因:還是因為GET是URL傳參給服務器  有一種比較簡單的黑客技術:URL劫持,也就是可以把客戶端傳遞給服務器的數據劫持掉,導致信息泄露 --- URL:請求數據的地址(API地址),真實項目中,后臺開發工程師會編寫一個API文檔,在API文檔中匯總了獲取哪些數據

需要使用哪些地址,我們按照文檔操作即可   ASYNC:異步(SYNC同步),設置當前AJAX請求是異步的還是同步的,不寫默認是異步(TRUE),如果設置為FALSE,

則代表當前請求是同步的   用戶名和密碼:這兩個參數一般不用,如果你請求的URL地址所在的服務器設定了訪問權限,則需要我們提供可通行的用

戶名和密碼才可以(一般服務器都是可以允許匿名訪問的)

 

**`第三部分細節研究`**
//=>監聽AJAX狀態改變,獲取響應信息(獲取響應頭信息、獲取響應主體信息) xhr.onreadystatechange=()=>{    if(xhr.readyState===4 && xhr.status===200){        let result=xhr.responseText;//=>獲取響應主體中的內容    } };

AJAX狀態碼:描述當前AJAX操作的狀態的
xhr.readyState

0:UNSENT 未發送,只要創建一個AJAX對象,默認值就是零
1:OPENED 我們已經執行了xhr.open這個操作
2:HEADERS_RECEIVED 當前AJAX的請求已經發送,并且已經接收到服務器端返回的響應頭信息了
3:LOADING 響應主體內容正在返回的路上
4:DONE 響應主體內容已經返回到客戶端


HTTP網絡狀態碼:記錄了當前服務器返回信息的狀態 xhr.status
200:成功,一個完整的HTTP事務完成(以2開頭的狀態碼一般都是成功)

以3開頭一般也是成功,只不過服務器端做了很多特殊的處理
301:Moved Permanently 永久轉移(永久重定向)一般應用于域名遷移
302:Move temporarily 臨時轉移(臨時重定向,新的HTTP版本中任務307是臨時重定向)一般用于服務器的負載均衡:當前服務器處理不了,我把當前請求臨時交給其他的服務器處理(一般圖片請求經常出現302,很多公司都有單獨的圖片服務器)
304:Not Modified 從瀏覽器緩存中獲取數據 把一些不經常更新的文件或者內容緩存到瀏覽器中,下一次從緩存中獲取,減輕服務器壓力,也提高頁面加載速度

以4開頭的,一般都是失敗,而且客戶端的問題偏大
400:請求參數錯誤
401:無權限訪問
404:訪問地址不存在

以5開頭的,一般都是失敗,而且服務器的問題偏大
500:Internal Server Error 未知的服務器錯誤
503:Service Unavailable 服務器超負載

AJAX中其它常用的屬性和方法

面試題:AJAX中總共支持幾個方法?

let xhr=new XMLHttpRequest();
console.dir(xhr);

[屬性]

  • readyState:存儲的是當前AJAX的狀態碼

  • response / responseText / responseXML :都是用來接收服務器返回的響應主體中的內容,只是根據服務器返回內容的格式不一樣,我們使用不同的屬性接收即可

    • responseText是最常用的,接收到的結果是字符串格式的(一般服務器返回的數據都是JSON格式字符串)

    • responseXML偶爾會用到,如果服務器端返回的是XML文檔數據,我們需要使用這個屬性接收

  • status:記錄了服務器端返回的HTTP狀態碼

  • statusText:對返回狀態碼的描述

  • timeout:設置當前AJAX請求的超時時間,假設我們設置時間為3000(MS),從AJAX請求發送開始,3秒后響應主體內容還沒有返回,瀏覽器會把當前AJAX請求任務強制斷開

[方法]

  • abort():強制中斷AJAX請求

  • getAllResponseHeaders():獲取全部的響應頭信息(獲取的結果是一堆字符串文本)

  • getResponseHeader(key):獲取指定屬性名的響應頭信息,例如:xhr.getResponseHeader(‘date’) 獲取響應頭中存儲的服務器的時間

  • open():打開一個URL地址

  • overrideMimeType():重寫數據的MIME類型

  • send():發送AJAX請求(括號中書寫的內容是客戶端基于請求主體把信息傳遞給服務器)

  • setRequestHeader(key,value):設置請求頭信息(可以是設置的自定義請求頭信息)

[事件]

  • onabort:當AJAX被中斷請求觸發這個事件

  • onreadystatechange:AJAX狀態發生改變,會觸發這個事件

  • ontimeout:當AJAX請求超時,會觸發這個事件


  •  

    

let xhr = new XMLHttpRequest();
// xhr.setRequestHeader('aaa', 'xxx');
//=>Uncaught DOMException: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED. 設置請求頭信息必須在OPEN之后和SEND之前
xhr.open('get', 'temp.xml?_=' + Math.random(), true);// xhr.setRequestHeader('cookie', '珠峰培訓');//=>Uncaught DOMException: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': '珠峰培訓' is not a valid HTTP header field value. 設置的請求頭內容不是一個有效的值(請求頭部的內容中不得出現中文漢字)xhr.setRequestHeader('aaa', 'xxx');//=>設置超時xhr.timeout = 100000; xhr.ontimeout = ()=> {    
   console.log('當前請求已經超時');    xhr.abort(); }; xhr.onreadystatechange = ()=> {    
   let {readyState:state, status}=xhr;    
   //=>說明請求數據成功了    if (!/^(2|3)\d{2}$/.test(status)) return;    
   //=>在狀態為2的時候就可以獲取響應頭信息    if (state === 2) {        
       let headerAll = xhr.getAllResponseHeaders(),            serverDate = xhr.getResponseHeader('date');
           //=>獲取的服務器時間是格林尼治時間(相比于北京時間差了8小時),通過new Date可以把這個時間轉換為北京時間            console.log(headerAll, new Date(serverDate));        
           return;    }    
   //=>在狀態為4的時候響應主體內容就已經回來了    if (state === 4) {        
       let valueText = xhr.responseText,
           //=>獲取到的結果一般都是JSON字符串(可以使用JSON.PARSE把其轉換為JSON對象)            valueXML = xhr.responseXML;
           //=>獲取到的結果是XML格式的數據(可以通過XML的一些常規操作獲取存儲的指定信息)  如果服務器返回的是XML文檔,responseText獲取的結果是字符串而responseXML獲取的是標準XML文檔            console.log(valueText, valueXML);    } }; xhr.send('name=zxt&age=28&sex=man');

 

JS中常用的編碼解碼方法

正常的編碼解碼(非加密)
1、escape / unescape:主要就是把中文漢字進行編碼和解碼的(一般只有JS語言支持:也經常應用于前端頁面通信時候的中文漢字編碼)

2、encodeURI / decodeURI:基本上所有的編程語言都支持

3、encodeURIComponent / decodeURIComponent:和第二種方式非常的類似,區別在于

也可以通過加密的方法進行編碼解碼
1、可逆轉加密(一般都是團隊自己玩的規則)
2、不可逆轉加密(一般都是基于MD5加密完成的,可能會把MD5加密后的結果二次加密)


需求:我們URL問號傳遞參數的時候,我們傳遞的參數值還是一個URL或者包含很多特殊的字符,此時為了不影響主要的URL,我們需要把傳遞的參數值進行編碼。使用encodeURI不能編碼一些特殊字符,所以只能使用encodeURLComponent處理

let str = 'http://www.baidu.com/?',     obj = {         name:'珠峰培訓',         age:9,         url:'http://www.got2p.com/?lx=1'     };
//=>把OBJ中的每一項屬性名和屬性值拼接到URL的末尾(問號傳參方式)
for(let key in obj){    str+=`${key}=${encodeURIComponent(obj[key])}&`;    
   //=>不能使用encodeURI必須使用encodeURIComponent,原因是encodeURI不能編碼特殊的字符}
   console.log(str.replace(/&$/g,''));
   //=>后期獲取URL問號參數的時候,我們把獲取的值在依次的解碼即可
   String.prototype.myQueryUrlParameter=function myQueryUrlParameter(){    
       let reg=/[?&]([^?&=]+)(?:=([^?&=]*))?/g,        obj={};    
       this.replace(reg,(...arg)=>{        
           let [,key,value]=arg;                    obj[key]=decodeURIComponent(value);//=>此處獲取的時候可以進行解碼            });    
   return obj; }

AJAX中的同步和異步

AJAX這個任務:發送請求接收到響應主體內容(完成一個完整的HTTP事務)
xhr.send():任務開始
xhr.readyState===4:任務結束

let xhr = new XMLHttpRequest(); xhr.open('get', 'temp.json', false); xhr.onreadystatechange = ()=> {    console.log(xhr.readyState); }; xhr.send();//=>只輸出一次結果是4

let xhr = new XMLHttpRequest(); xhr.open('get', 'temp.json', false); xhr.send();
//=>[同步]開始發送AJAX請求,開啟AJAX任務,在任務沒有完成之前,什么事情都做不了(下面綁定事件也做不了) => LOADING => 當readyState===4的時候AJAX任務完成,開始執行下面的操作//=>readyState===4

xhr.onreadystatechange = ()=> {    
   console.log(xhr.readyState); };
//=>綁定方法之前狀態已經為4了,此時AJAX的狀態不會在改變成其它值了,所以事件永遠不會被觸發,一次都沒執行方法(使用AJAX同步編程,不要把SEND放在事件監聽前,這樣我們無法在綁定的方法中獲取到響應主體的內容)
let xhr = new XMLHttpRequest(); xhr.open('get', 'temp.json'); xhr.onreadystatechange = ()=> {    
   console.log(xhr.readyState); }; xhr.send();//=>輸出3次,結果分別是 2 3 4

let xhr = new XMLHttpRequest(); xhr.open('get', 'temp.json'); xhr.send();
//=>xhr.readyState===1
xhr.onreadystatechange = ()=> {    
   console.log(xhr.readyState); };//=>2 3 4
let xhr = new XMLHttpRequest(); xhr.onreadystatechange = ()=> {    
   console.log(xhr.readyState); }; xhr.open('get', 'temp.json'); xhr.send();//->1 2 3 4
let xhr = new XMLHttpRequest();//=>xhr.readyState===0
xhr.onreadystatechange = ()=> {    
   console.log(xhr.readyState); }; xhr.open('get', 'temp.json', false);
//=>xhr.readyState===1 AJAX特殊處理的一件事:執行OPEN狀態變為1,會主動把之前監聽的方法執行一次,然后再去執行SEND
xhr.send();
//=>xhr.readyState===4 AJAX任務結束,主任務隊列完成//=>1 4

實戰案例:倒計時搶購

~function () {    let box = document.getElementById('box'),         serverTime = null;    let fn = ()=> {        
       //=>1、計算當前時間和目標時間的差值        //=>new Date():獲取的是客戶端本機時間(會受到客戶端自己調整時間的影響),重要的時間參考不能基于這個完成,不管是哪一個客戶端都需要基于相同的服務器時間計算        //=>每間隔1S中,我們需要把第一次獲取的服務器時間進行累加        serverTime = serverTime + 1000;        
       let tarTime = new Date('2017/12/14 13:12:20').getTime(),            spanTime = tarTime - serverTime;        
           //=>2、計算差值中包含多少時分秒        if (spanTime < 0) {            
           //=>已經錯過了搶購的時間(已經開搶了)            box.innerHTML = '開搶啦!!';            clearInterval(autoTimer);            
           return;        }        
       let hours = Math.floor(spanTime / (1000 * 60 * 60));        spanTime -= hours * 3600000;        
       let minus = Math.floor(spanTime / (1000 * 60));        spanTime -= minus * 60000;        
       let seconds = Math.floor(spanTime / 1000);        hours < 10 ? hours = '0' + hours : null;        minus < 10 ? minus = '0' + minus : null;        seconds < 10 ? seconds = '0' + seconds : null;        box.innerHTML = `距離開搶還剩下 ${hours}:${minus}:${seconds}`;    };    
   let autoTimer = setInterval(fn, 1000);    
   //=>從服務器端獲取服務器時間    let getServerTime = ()=> {        
   let xhr = new XMLHttpRequest();        xhr.onreadystatechange = ()=> {            
       //console.log(xhr.readyState);
       //=>HEAD請求方式,狀態碼中沒有3(不需要等待響應主體內容)
           if (!/^(2|3)\d{2}$/.test(xhr.status)) return;            
               if (xhr.readyState === 2) {                serverTime = new Date(xhr.getResponseHeader('date')).getTime();                fn();            }        };        xhr.open('head', 'temp.xml', true);        xhr.send(null);        /*         * 獲取服務器時間總會出現時間差的問題:服務器端把時間記錄好,到客戶端獲取到事件有延遲差(服務器返回的時候記錄的是10:00,我們客戶端獲取的時候已經是10:01,但是我們獲取的結果依然是10:00,這樣就有1分鐘時間差)         *         * [盡可能的減少時間差,是我們優化的全部目的]         *         * 1、服務器返回的時間在響應頭信息中就有,我們只需要獲取響應頭信息即可,沒必要獲取響應主體內容,所以請求方式使用 HEAD 即可         * 2、必須使用異步編程:同步編程我們無法在狀態為2或者3的時候做一些處理,而我們獲取響應頭信息,在狀態為2的時候就可以獲取了,所以需要使用異步         * 3、在狀態為2的時候就把服務器時間獲取到         * ...         */    };    getServerTime(); }();

AJAX類庫的封裝

JQ中的AJAX使用及每一個配置的作用(包含里面的一些細節知識)

$.ajax({     url:'xxx.txt',//=>請求API地址     method:'get',//=>請求方式GET/POST...在老版本JQ中使用的是type,使用type和method實現的是相同的效果     dataType:'json',//=>dataType只是我們預設獲取結果的類型,不會影響服務器的返回(服務器端一般給我們返回的都是JSON格式字符串),如果我們預設的是json,那么類庫中將把服務器返回的字符串轉換為json對象,如果我們預設的是text(默認值),我們把服務器獲取的結果直接拿過來操作即可,我們預設的值還可以是xml等     cache:false,//=>設置是否清除緩存,只對GET系列請求有作用,默認是TRUE不清緩存,手動設置為FALSE,JQ類庫會在請求URL的末尾追加一個隨機數來清除緩存     data:null,//=>我們通過DATA可以把一些信息傳遞給服務器;GET系列請求會把DATA中的內容拼接在URL的末尾通過問號傳參的方式傳遞給服務器,POST系列請求會把內容放在請求主體中傳遞給服務器;DATA的值可以設置為兩種格式:字符串、對象,如果是字符串,設置的值是什么傳遞給服務器的就是什么,如果設置的是對象,JQ會把對象變為 xxx=xxx&xxx=xxx 這樣的字符串傳遞給服務器     async:true,//=>設置同步或者異步,默認是TRUE代表異步,FALSE是同步     success:function(result){        //=>當AJAX請求成功 (readyState===4 & status是以2或者3開頭的)         //=>請求成功后JQ會把傳遞的回調函數執行,并且把獲取的結果當做實參傳遞給回調函數    (result就是我們從服務器端獲取的結果)     },     error:function(msg){},//=>請求錯誤觸發回調函數     complate:function(){},//=>不管請求是錯誤的還是正確的都會觸發回調函數(它是完成的意思)     ... });

封裝屬于自己的AJAX類庫

[支持的參數]

url

method / type

data

dataType

async

cache

success


 

~function () {     class ajaxClass {         //=>SEND AJAX         init() {             //=>THIS:EXAMPLE             let xhr = new XMLHttpRequest();             xhr.onreadystatechange = ()=> {                 if (!/^[23]\d{2}$/.test(xhr.status)) return;                 if (xhr.readyState === 4) {                     let result = xhr.responseText;                     //=>DATA-TYPE                     try {                         switch (this.dataType.toUpperCase()) {                             case 'TEXT':                             case 'HTML':                                 break;                             case 'JSON':                                 result = JSON.parse(result);                                 break;                             case 'XML':                                 result = xhr.responseXML;                         }                     } catch (e) {                      }                     this.success(result);                 }             };              //=>DATA             if (this.data !== null) {                 this.formatData();                  if (this.isGET) {                     this.url += this.querySymbol() + this.data;                     this.data = null;                 }             }              //=>CACHE             this.isGET ? this.cacheFn() : null;              xhr.open(this.method, this.url, this.async);             xhr.send(this.data);         }          //=>CONVERT THE PASSED OBJECT DATA TO STRING DATA         formatData() {             //=>THIS:EXAMPLE             if (Object.prototype.toString.call(this.data) === '[object Object]') {                 let obj = this.data,                     str = ``;                 for (let key in obj) {                     if (obj.hasOwnProperty(key)) {                         str += `${key}=${obj[key]}&`;                     }                 }                 str = str.replace(/&$/g, '');                 this.data = str;             }         }          cacheFn() {             //=>THIS:EXAMPLE             !this.cache ? this.url += `${this.querySymbol()}_=${Math.random()}` : null;         }          querySymbol() {             //=>THIS:EXAMPLE             return this.url.indexOf('?') > -1 ? '&' : '?';         }     }      //=>INIT PARAMETERS     window.ajax = function ({         url = null,         method = 'GET',         type = null,         data = null,         dataType = 'JSON',         cache = true,         async = true,         success = null     }={}) {         let _this = new ajaxClass();         ['url', 'method', 'data', 'dataType', 'cache', 'async', 'success'].forEach((item)=> {             if (item === 'method') {                 _this.method = type === null ? method : type;                 return;             }             if (item === 'success') {                 _this.success = typeof success === 'function' ? success : new Function();                 return;             }             _this[item] = eval(item);         });         _this.isGET = /^(GET|DELETE|HEAD)$/i.test(_this.method);         _this.init();         return _this;     }; }();

上一篇: 關于React腳手架的一點研究

下一篇: 面向對象深入解讀

我要看A级毛片_多多屋影院,中文字幕国产在线播放,日本近親倫亂中文字幕AV視頻 <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>