原生的Ajax實現

ACodingIceBear發表於2018-01-08

原生的Ajax實現步驟

1.原生js中的建構函式XMLHTTPRequest()構造例項;

考慮相容問題:
if(window.XMLHttpRequest){
	var xhr = new XMLHTTPRequest();
}else{
	var xhr = new ActiveXObject();
}
複製程式碼

2.例項化為物件後,要建立一個請求,準備好一個請求的發射視窗狀態;

xhr.open("get/post", "請求地址", true);
複製程式碼

3.send方法發出請求,引數是傳送的報文體,get方法時報文體為空null,post方法才有內容;

xhr.send(null);
複製程式碼

4.JS中需要監聽資料什麼時候回來的機制,使用一個事件監聽就緒狀態,當xhr的狀態改變是觸發;

xhr.onreadystatechange = function(){
	if(xhr.readyState == 4){
		//xhr的readyState有5個數值,表示不同狀態,4表示接受檔案完成,{}內表示接受完成之後執行的操作
		document.getElementById().innerHTML = xhr.responseText;
	}
}
複製程式碼

狀態的監聽要放在建立例項物件和open呼叫之間,確切的說新增事件應該是第二步,

  • readyState的屬性值:

    0: 未初始化,此時XMLHTTPRequest物件已經建立,還沒有呼叫open();

    1: 已經建立請求,呼叫open函式,但是還沒有呼叫send傳送;

    2: 請求已經傳送,正在處理中,此時已經接受了response的報文頭部;

    3: 請求處理中,此時已經接收了部分報文體,response中的部分資料已經可以使用;

    4: 響應完成,可以使用報文的全部資訊。

  • 注意:為了防止快取(304),呼叫open時,在第二個引數請求地址後新增一個隨機數,保證每次訪問的地址不同,避免因為快取導致請求的檔案發生改變,而頁面並未隨之改變(因為使用了快取的資料)。

xhr.open("get", "demo/demo.txt?" + Math.random(), true);
複製程式碼

post請求和get請求的區別

xhr.open("post", "請求檔案", true);

//設定請求頭部傳送時的文字格式,因為post方法只能通過表單格式傳送
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

//send方法中的引數是報文體,而post方法傳遞是通過報文體,呼叫send方法傳遞的引數是以kv對形式的字串,類似query string
xhr.send("k=v&k=v");
複製程式碼

原生的post是將傳遞的引數放到send()中以form data形式傳遞,而原生的get方法是將資料放到第二個引數的路徑?後面,以查詢字串的形式傳遞,這和jQuery的傳遞方法不同,jQuery中的$.get()和$.post()都是通過第二個引數以json的形式傳遞到介面頁面的。 在介面頁面中,比如PHP頁面中,獲取傳遞的資料方法

$getdata = $_GET["k值"];
$postdata = $_POST["k值"];
複製程式碼
但是通常引數是以json形式傳遞的,如何將json物件轉換為鍵值對形式的字串?
var data = {
	"names": "Tom",
	"age": 19,
	"sex": "男"
}

//封裝一個格式轉換函式
function changeToString(JSON){
	var tempArr = [];
	for(var k in JSON){
		//url只允許英文、數字和特殊字元,當有中文或其他國家語言出現時,要通過uri(統一資源識別符號)來轉換
		tempArr.push(k + "=" + encodeURIComponent(JSON[k]));
	}
	return temp.join("&");
}

//呼叫函式轉換格式
xhr.send(changeToString(data));
複製程式碼
那麼從後臺傳送來的資料,前端並不知道資料是什麼格式,也就不能直接拿來就使用,要先進行判斷:

如果負責的後臺在介面檔案中將陣列轉換為json物件再發回前端,那麼前端只要做判斷就可以了。

<?php
	//header('Content-type: application/json');
	$arr = array(...);
	
	//json_encode將陣列變為json物件形式
	echo json_encode($arr);
?>
複製程式碼
  • 判斷方法一:使用JSON.parse()方法將字串轉換為json物件,但是有相容問題存在,IE6,7,8不相容這個方法。
使用jQuery的get方法
$.get("data.php", function(data){
	
	//data是從後臺傳回的response資料,要先判斷是JSON物件還是JSON物件形式的字串
	var dataObj = typeof data == "object" ? data : JSON.parse(data);
})
複製程式碼
  • 判斷方法二:使用eval()方法,沒有相容問題,eval()可以將str變成執行語句,但是轉換物件形式的字串要注意,字串外面必須加括號。
	var dataObj = typeof data == "object" ? data : eval("("+ data +")");
複製程式碼
  • 判斷方法三:使用內建建構函式Function(), 通過建構函式new的例項立即執行返回json物件。
	var dataObj = typeof data == "object" ? data : (new Function("return" + data))();
複製程式碼

建構函式的引數當有多個時,最後一個為執行語句,前面的都是引數,而當只有一個時,這個引數就是執行語句,立即呼叫執行可以直接返回。

原生的Ajax可能在平時用到並不多,因為有像jQuery這些提供了更方便的方法,但還是要知道是怎樣實現的。Ajax另一個重要的概念是跨域的問題,等學完再專門寫一篇跨域的小結。

相關文章