從零開始學 Web 之 Ajax(三)Ajax 概述,快速上手
大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新......
- github:https://github.com/Daotin/Web
- 微信公眾號:Web前端之巔
- 博客園:http://www.cnblogs.com/lvonve/
- CSDN:https://blog.csdn.net/lvonve/
在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的項目。現在就讓我們一起進入 Web 前端學習的冒險之旅吧!
一、Ajax 概述
Ajax 全稱:Asynchronous JavaScript and XML(異步 JavaScript 和 XML)。它不是一種新的編程語言,而是一種用於創建更好更快以及交互性更強的Web應用程序的技術。它可以在無需重新加載整個網頁的情況下,能夠更新部分網頁的技術。而傳統的網頁(不使用 AJAX)如果需要更新內容,必需重載整個網頁面。
還有為什麽叫異步呢?
因為在加載的時候,頁面的其他部分還是可以自由操作的,沒有出現卡死的狀態,所以是異步。
有很多使用 AJAX 的應用程序案例:新浪微博、Google 地圖、開心網等等。
在此之前,我們可以通過以下幾種方式讓瀏覽器發出對服務端的請求,獲得服務端的數據:
- 地址欄輸入地址,回車,刷新
- 特定元素的 href 或 src 屬性
- 表單提交
這些方案都是我們無法通過或者很難通過代碼的方式進行編程(對服務端發出請求並且接受服務端返回的響應) 。
如果仔細觀察一個Form的提交,你就會發現,一旦用戶點擊“Submit”按鈕,表單開始提交,瀏覽器就會刷新頁面,然後在新頁面裏告訴你操作是成功了還是失敗了。如果不幸由於網絡太慢或者其他原因,就會得到一個404頁面。
這就是Web的運作原理:一次HTTP請求對應一個頁面。
如果要讓用戶留在當前頁面中,同時發出新的HTTP請求,就必須用JavaScript發送這個新請求,接收到數據後,再用JavaScript更新頁面,這樣一來,用戶就感覺自己仍然停留在當前頁面,但是數據卻可以不斷地更新。
最早大規模使用AJAX的就是Gmail,Gmail的頁面在首次加載後,剩下的所有數據都依賴於AJAX來更新。
用JavaScript寫一個完整的AJAX代碼並不復雜,但是需要註意:AJAX請求是異步執行的,也就是說,要通過回調函數獲得響應。
二、Ajax快速上手
使用 Ajax 的過程可以類比平常我們訪問網頁過程 :
// 1. 創建一個 XMLHttpRequest 類型的對象 —— 相當於打開了一個瀏覽器 var xhr = null; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } // 2. 打開與一個網址之間的連接 —— 相當於在地址欄輸入訪問地址 xhr.open("get", "checkusername.php?username=" + uname, true); // 3. 通過連接發送一次請求 —— 相當於回車或者點擊訪問發送請求 xhr.send(null); // 僅僅針對 post 請求 //xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 4. 指定 xhr 狀態變化事件處理函數 —— 相當於處理網頁呈現後的操作 xhr.onreadystatechange = function () { if (this.readyState == 4) { if (this.status == 200) { console.log(this.responseText); } } };
1、創建對象
在IE6及以下的時候,是不支持 XMLHttpRequest 對象的,那麽與之對應寫法為:
var xhr = new ActiveXObject("Microsoft.XMLHTTP");
所以為了兼容性,上面的創建對象的方式改為:
var xhr = null;
if(window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
2、open 方法
第一個參數是請求的方式,是 get 請求還是 post 請求。一般取決後端開發的php文件裏面寫的是 get 還是 post。
第二個參數是需要請求的地址。如果是 get 請求,需要在地址後面加上 ? 進行連接操作,連接的是需要請求的你內容。(參考下面驗證用戶名示例),如果是 post 請求,只需要寫請求的地址就可以了,它的請求內容是寫在 send 中的。
第三個參數是同步或者異步,一般可以不寫,不寫默認異步,false:同步,true:異步。
3、send 方法
對於 get 方式,參數為 null;
對於 post 方式,參數為請求的數據。
var param = "username=" + uname; // 和 get 地址後面 ? 鏈接請求內容一致
shr.send(param);
對於 post 請求,還需要設置下請求頭(post請求才有)
// 僅僅針對 post 請求才有
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
4、onreadystatechange 回調函數
之所以是回調函數,這樣不會阻塞當前的操作,什麽時候服務器返回數據,什麽時候使用。這就是異步。
status:服務器返回的狀態碼
this.status == 200:表示響應成功;404 表示沒有找到請求的資源;500 表示服務器端錯誤。
readyState:
xhr對象的狀態改變時,readyState的值也會相應的改變。具體數值的含義見下表:
readyState | xhr狀態 | 說明 |
---|---|---|
0 | UNSENT | 代理(xhr)被創建,但尚未調用 open 方法 |
1 | OPENED | open 方法已經被調用,建立了連接 |
2 | HEADERS_RECEIVED | send 方法已經被調用,已經可以獲取狀態行和響應頭 |
3 | LOADING | 響應體下載中,responseText 屬性可能已經包含部分數據 |
4 | DONE | 響應體下載完成,可以直接調用 responseText 獲取數據 |
詳細解析代碼:
var xhr = new XMLHttpRequest();
console.log(xhr.readyState);
// => 0
// 初始化 請求代理對象
xhr.open('GET', 'time.php');
console.log(xhr.readyState);
// => 1
// open 方法已經調用,建立一個與服務端特定端口的連接
xhr.send();
xhr.addEventListener('readystatechange', function () {
switch (this.readyState) {
case 2:
// => 2
// 已經接受到了響應報文的響應頭
// 可以拿到頭
// console.log(this.getAllResponseHeaders())
console.log(this.getResponseHeader('server'));
// 但是還沒有拿到體
console.log(this.responseText);
break;
case 3:
// => 3
// 正在下載響應報文的響應體,有可能響應體為空,也有可能不完整
// 在這裏處理響應體不保險(不可靠)
console.log(this.responseText);
break;
case 4:
// => 4
// 一切 OK (整個響應報文已經完整下載下來了)
// 這裏處理響應體
console.log(this.responseText);
break;
}
});
當 readyState == 2 時,只獲取到數據頭,這時不能使用 responseText 獲取,而是用 getResponseHeader 來獲取數據頭信息。
當 readyState == 3 時,可能已經獲取部分數據體,但是處理數據是不可靠的,所以一般一般我們都是在 readyState 值為 4 時,執行響應的後續邏輯 。
其實,當 onreadystatechange 執行時 並且 readyState == 4 的時候,在 HTML5 中有了更加便捷的寫法:
xhr.onload = function () {
console.log(this.readyState); // 4
console.log(this.readyState);
}
三、案例:點擊按鈕驗證用戶名是否存在
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<h1>用戶註冊</h1>
用戶名:
<input type="text" name="username">
<input type="button" value="驗證用戶名" id="btn">
<span></span>
<br> 密碼:
<input type="password" name="passwd">
<br>
<input type="submit" value="註冊提交">
</div>
<script>
var spanObj = document.getElementsByTagName("span")[0];
document.getElementById("btn").onclick = function () {
// 獲取用戶名
var uname = document.getElementsByName("username")[0].value;
// 發送給服務器處理
var xhr = new XMLHttpRequest();
xhr.open("get", "checkusername.php?username=" + uname, true);
xhr.send(null);
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
spanObj.innerText = xhr.responseText;
if (xhr.responseText == "用戶名已存在!") {
spanObj.style.color = "red";
} else {
spanObj.style.color = "green";
}
}
};
};
</script>
</body>
</html>
後臺 PHP代碼:
<?php
$user = $_GET["username"];
if($user == "lvonve") { // 這裏僅僅只判斷一個用戶名,實際上是由數據庫提供
echo "用戶名已存在!";
} else {
echo "用戶名可以使用!";
}
?>
從零開始學 Web 之 Ajax(三)Ajax 概述,快速上手