什麼是AJAX?javascript
async javascript and xml 異步的JS和XMLphp
做用:是用來存儲數據的(經過本身擴展的標記名稱清晰地展現出數據結構)html
ajax之因此稱爲異步的js和xml,主要緣由是:之前最開始使用ajax實現客戶端和服務端數據通訊的時候,傳輸數據的格式通常都是xml格式的數據,咱們把他稱之爲異步的js和xml(如今通常都是基於JSON格式來進行數據傳輸的)前端
<?xml version="1.0" encoding="UTF-8"?>
<root>
<student>
<name>海洋</name>
<age>10</age>
<score>
<deutsch>100</deutsch>
<IT>100</IT>
<english>100</english>
</score>
</student>
</root>
複製代碼
這裏的異步不是說ajax只能基於異步進行請求(雖然建議都是使用異步編程),這裏的異步特指的是 局部刷新java
全局刷新:git
在非徹底先後端分離的項目中,前端開發只須要完成頁面的製做,而且把一些基礎的人機交互效果使用js完成便可,頁面中須要動態呈現內容的部分,都是交給後臺開發工程師作數據綁定和基於服務器進行渲染的(服務器端渲染)github
非徹底先後端分離: 面試
【優點】ajax
- 動態展現的數據在頁面的源代碼中能夠看見,有利於SEO優化推廣(有利於搜索引擎的收錄和抓取)
- 從服務器端獲取的結果已是解析渲染完成的了,不須要客戶端再去解析渲染了,因此頁面加載速度快(前提是服務器端處理的速度夠快,可以處理過來),因此相似於京東,淘寶這些網站,首屏數據通常都是由服務器端渲染的
【弊端】編程
- 若是頁面中存在實時更新的數據,每一次想要展現最新的數據,頁面都要從新刷新一次,這樣確定不行,很是耗性能
- 都交給服務器端作數據渲染,服務器端的壓力太大,若是服務器處理不過來,頁面呈現的速度更慢(因此像京東和淘寶這類的網站,除了首屏是服務器端渲染的,其餘屏通常都是客戶端作數據渲染綁定的)
- 這種模式不利於開發,(開發效率低)
局部刷新
目前市場上大部分項目都是先後端徹底分離的項目(也有非徹底先後端分離的佔少數)
先後端徹底分離的項目,頁面中須要動態綁定的數據是交給客戶端完成渲染的
- 向服務器端發送AJAX請求
- 把從服務器端獲取的數據解析處理,拼接成咱們須要展現的HTML字符串
- 把拼接好的字符串替換頁面中的某一部份內容(局部刷新),頁面不須要總體從新加載,局部渲染便可
先後端徹底分離:
![]()
【優點】
咱們能夠根據需求,任意修改頁面中的某一部份內容(例如實時刷新),總體頁面不刷新,性能好,體驗好(全部表單驗證,須要實時刷新的等需求都要基於AJAX實現)
有利於開發,提升開發效率
1)先後端的徹底分離,後臺不須要考慮前端如何實現,前端也不須要考慮後臺用什麼技術,真正意義上實現了技術的劃分
2)能夠同時進行開發:項目開發開始,首先制定先後端數據交互的接口文檔(文檔中包含了,調取哪一個接口或者哪些數據等協議規範),後臺把接口先寫好(目前不少公司也須要前端本身拿NODE來模擬這些接口),客戶端按照接口調取便可,後臺再去實現接口功能便可
【弊端】
- 不利於SEO優化:第一次從服務器端獲取的內容不包含須要動態綁定的數據,因此頁面的源代碼中沒有這些內容,不利於SEO收錄,後期經過JS添加到頁面中的內容,並不會寫在頁面的源代碼中(是源代碼不是頁面結構)
- 交由客戶端渲染,首先須要把頁面呈現,而後在經過JS的異步AJAX請求獲取數據,在進行數據綁定,瀏覽器再把動態增長的部分從新渲染,無形中浪費了一些時間,沒有服務器端渲染頁面呈現速度快
// 建立一個AJAX對象
let xhr = new XMLHttpRequest(); // 不兼容IE6及更低版本瀏覽器(IE6:ActiveXObject)
// 打開請求地址(能夠理解爲一些基礎配置,可是並無發送請求呢)
xhr.open([method],[url],[async],[userName],[passWord]);
// 監聽AJAX狀態改變,獲取響應信息(獲取響應頭信息,獲取響應主體信息)
xhr.onreadystatechange = ()=>{
if(xhr.readyState === 4 && xhr.status === 200){
let result = xhr.responseText; // 獲取響應主體中的內容
}
};
// 發送AJAX請求(括號中傳遞的內容就是請求主體的內容)
xhr.send(null);
複製代碼
分析第二步中的細節點
xhr.open([method],[url],[async],[userName],[passWord])
[AJAX請求方式]
- GET請求系列(獲取)
- get
- delete:從服務器上刪除某些資源文件
- head:只想獲取服務器返回的響應頭信息(響應主體不須要獲取)
- POST請求系列(推送)
- post
- put:向服務器中增長指定的資源文件
無論哪種請求方式,客戶端均可以把信息傳遞給服務器端,服務器端也能夠把信息返回給客戶端,只是GET系列通常以獲取爲主(給的少,拿回來的多),而POST系列通常以推送爲主(給的多,拿回來的少)
1)咱們想要獲取一些動態展現的信息,通常使用GET請求,由於只須要向服務器端發送請求,告訴服務器端咱們想要什麼,服務器端就會把須要的數據返回
2)在實現註冊功能的時候,咱們須要把客戶輸入的信息發送給服務器進行存儲,服務器通常返回成功或失敗等狀態,此時咱們通常都是基於POST請求完成的
GET系列請求和POST系列請求,在項目實戰中存在不少的區別
GET請求傳遞給服務器的內容通常沒有POST請求傳遞給服務器的內容多
緣由:GET請求傳遞給服務器內容通常都是基於 URL地址問號傳遞參數 來實現的,而POST請求通常都是基於 設置請求主體 來實現的,各個瀏覽器都有URL最大長度的限制(谷歌:8kb,火狐:7kb,IE:2kb),超出長度部分,瀏覽器會自動截取掉,致使傳遞給服務器的數據缺失
理論上POST請求經過請求主體傳遞是沒有大小限制的,真實項目中爲了保證傳輸的速率,咱們也會限制大小(例如:上傳的資料或者圖片咱們會作大小的限制)
GET請求很容易出現緩存(這個緩存不可控,通常咱們都不須要),而POST不會出現緩存(除非本身作特殊處理)
緣由:GET是經過URL問號傳參傳遞給服務器信息,會出現緩存;而POST是設置請求主體,不會出現緩存。
// 每隔一分鐘從新請求服務器端最新的數據,而後展現在頁面中(頁面中某些數據實時刷新)
setTimeout(()=>{
$.ajax({
url: 'getList?lx = news',
...
success: result=>{
// 第一次請求數據回來,間隔一分鐘後,瀏覽器又發送一次請求,可是新發送的請求不管是地址仍是傳遞的參數都和第一次如出一轍,瀏覽器頗有可能會把上一次的數據獲取,而不是獲取最新的數據
}
})
},600)
// 解決方案:在每一次從新請求的時候,在URL的末尾追加一個隨機數,保證每一次請求的地址不徹底一致,就能夠避免是從緩存中讀取的數據
setTimeout(()=>{
$.ajax({
url: 'getList?lx = news&_=' + Math.random(),
...
success: result=>{
}
})
},600)
複製代碼
GET請求沒有POST請求安全(POST也並非十分安全,只是相對安全)
緣由:仍是由於GET是URL傳參給服務器
有一種比較簡單的黑客技術:URL劫持,也就是能夠把客戶端傳遞給服務器的數據劫持到,致使信息泄露
URL:請求數據的地址(API地址),在真實項目中,後臺開發工程師會編寫一個API文檔,在API文檔中彙總了獲取哪些數據須要使用哪些地址,咱們按照文檔操做便可
ASYNC:異步(SYNC 同步),設置當前AJAX請求是異步的仍是同步的,不寫默認是異步(TRUE),若是設置爲FALSE,則表明當前請求是同步的
用戶名和密碼:這兩個參數通常不用,若是你請求的URL地址所在的服務器設定了訪問權限,則須要咱們提供可通行的用戶名和密碼才能夠(通常服務器都是能夠匿名訪問的)
分析第三步中的細節點
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中總共支持幾個方法?
let xhr = new XMLHttpRequest();
console.dir(xhr);
//【屬性】
// 1.readyState:存儲的是當前AJAX的狀態碼
// response/responseText/responseXML:都是用來接收服務器返回的響應主體中的內容,只是根據服務器返回內容格式的不同,咱們使用不一樣的屬性接收便可
// responseText是最經常使用的,接收的結果是字符串格式的(通常服務器返回的數據都是JSON格式字符串)
// responseXML偶爾會用到,若是服務器返回的是XML文檔數據,咱們須要使用這個屬性接收
// status:記錄了服務器端返回的HTTP狀態碼
// statusText:對返回的狀態碼的描述
// timeout:設置當前AJAX請求的超時時間,假設咱們設置時間爲3000ms,從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.open('get','temp.json?_=' + Math.random(), true);
xhr.setRequestHeader('aaa', '123'); // 注意:請求頭部的內容不得出現中文漢字。設置請求頭信息必須在OPEN以後和SEND以前
// 設置超時
xhr.timeout = 10;
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=hy&age=6&sex=man');
複製代碼
正常的編碼解碼(非加密)
- escape / unescape: 主要就是把中文漢字進行編碼和解碼(通常只有JS語言支持:也常常應用於前端頁面通訊時候的中文漢字編碼)
str = '你好海洋 哈哈'
"你好海洋 哈哈"
escape(str)
"%u4F60%u597D%u6D77%u6D0B%20%u54C8%u54C8"
unescape("%u4F60%u597D%u6D77%u6D0B%20%u54C8%u54C8")
"你好海洋 哈哈"
複製代碼
- encodeURI / decodeURI : 基本上全部的編程語言都支持
str = '你好海洋 哈哈'
"你好海洋 哈哈"
encodeURI(str)
"%E4%BD%A0%E5%A5%BD%E6%B5%B7%E6%B4%8B%20%E5%93%88%E5%93%88"
decodeURI("%E4%BD%A0%E5%A5%BD%E6%B5%B7%E6%B4%8B%20%E5%93%88%E5%93%88")
"你好海洋 哈哈"
複製代碼
encodeURIComponent / decodeURIComponent 和第二種方式很是相似,區別在於:
當咱們經過URL問號傳參的時候,咱們傳遞的參數值仍是一個URL或者包含不少的特殊字符,此時爲了避免影響主要的URL,咱們須要把傳遞的參數值進行編碼,使用encodeURI不能編碼一些特殊字符,因此只能使用恩codeURLComponent處理
str = '你好海洋 哈哈'
"你好海洋 哈哈"
encodeURIComponent(str)
"%E4%BD%A0%E5%A5%BD%E6%B5%B7%E6%B4%8B%20%E5%93%88%E5%93%88"
decodeURIComponent("%E4%BD%A0%E5%A5%BD%E6%B5%B7%E6%B4%8B%20%E5%93%88%E5%93%88")
"你好海洋 哈哈"
複製代碼
let str = 'http://wudiufo.github.io/?',
obj = {
name:'haiyang',
age:'8';
url:'http://www.haiyang.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;
}
複製代碼
也能夠經過加密的方法進行編碼解碼
可逆轉加密(通常都是團隊本身用的規則)
不可逆轉加密(通常都是基於MD5完成的,可能會把MD5加密後的結果二次加密)
AJAX這個任務:發送請求接收到響應主體內容(完成一個完整的HTTP事務)
xhr.send() : 任務開始
xhr.readState===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
複製代碼
1,結構:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="box"></div>
<script src="./1.js"></script>
</body>
</html>
複製代碼
2, 交互:
~ function() {
let box = document.getElementById('box');
let serverTime = null;
let fn = () => {
// 1,計算當前時間和目標時間的差值
// new Date():獲取的是客戶端本機時間(會受到客戶端本身調整時間的影響),重要的時間參考不能基於這個完成,不論哪個客戶端都要基於相同的服務器時間計算
// 每間隔一秒鐘,咱們須要把第一次獲取的服務器時間進行累加
serverTime = serverTime + 1000;
let tarTime = new Date('2018/12/22 12:00:00').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);
// 1,服務器返回的時間在響應頭就有,咱們只須要獲取響應頭信息便可,不必獲取響應主體內容,因此請求方式使用HEAD便可
// 2,必須使用異步編程:同步編程咱們沒法再狀態爲2或3的時候作一些處理,而咱們獲取響應頭信息,在狀態爲2的時候就能夠獲取了,因此須要使用異步
// 3,在狀態爲2的時候就把服務器時間獲取到
// 獲取服務器時間總會出現時間差的問題,服務器端把時間記錄好,到客戶端獲取到時間有延遲差(例如:服務器返回的時候記錄的是10:00,到客戶端獲取的時候已是10:01,可是客戶端獲取的結果依然是10:00,這樣就有了1秒鐘的時間差)【儘量的減小時間差,是咱們優化的所有目的】
};
getServerTime();
}();
複製代碼
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或者4開頭的)
// 請求成功後JQ會把傳遞的回調函數執行,而且把獲取的結果當作實參傳遞給回調函數(result就是咱們從服務器獲取的結果)
},
error:function(msg){}, // 請求錯誤觸發回調函數
complete:function(){}, // 不論請求是錯誤的仍是正確的都會觸發回調函數(他是完成的意思)
})
複製代碼
【支持的參數】
url
method/type
data
dataType
async
cache
success
~ function() {
class ajaxClass {
// SEND AJAX
init() {
// THIS:EXAMPLE
let xhr = new XMLsHttpRequest();
xhr.onreadystatechange = () => {
if (!/[23]\d{2}$/.test(xhr.status)) return;
if (xhr.readyState === 4) {
let result = xhr.responseText;
// DATA-TYPE
switch (this.dataType.toUpperCase()) {
case 'TEXT':
case 'HTML':
break;
case 'JSON':
result = JSON.parse(result);
break;
case 'XML':
result = xhr.responseXML;
}
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);
}
// 把傳遞的對象格式data轉換爲字符串格式的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.querySymbol.indexof('?') > -1 ? '&' : '?';
}
}
// init parameters
window.ajax = function({ url = null, method = 'GET', type = 'null', data = null, dataType = 'JSON', cache = true, async = true, success = null } = {}) {
let example = new ajaxClass();
example.url = url;
example.method = type === null ? method : type;
example.data = data;
example.dataType = dataType;
example.cache = cache;
example.async = async;
example.success = typeof success === 'function' ? success : new Function();
example.isGET = /^(GET|DELETE|HEAD)$/i.test(example.method);
example.init();
return example;
};
}();
ajax({});
複製代碼
優化代碼:
~ 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);
}
// 把傳遞的對象格式data轉換爲字符串格式的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.querySymbol.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;
};
}();
ajax({});
複製代碼