我是專註於軟件開發和IT教育的孫鑫老師,出版過多本計算機圖書,包括《Java Web開發詳解》、《VC++深入詳解》、《Struts 2深入詳解》、《Servlet/JSP深入詳解》、《XML、XML Schema、XSLT 2.0和XQuery開發詳解》、《HTML5、CSS和JavaScript開發》、《Vue.js從入門到實戰》、《Java無難事》、《Vue.js 3.0從入門到實戰》。
喜歡我的文章歡迎關注、轉發、評論、點贊和收藏,我會經常與大家分享IT技術、編程語言的文章和教學視頻。目前已發布完整的《Vue.js從入門到實戰》和《Java無難事》教學視頻,正在發布《Vue.js 3.0從入門到實戰》一書教學視頻。
現在學習前端開發的同學很多,很多JavaScript庫與框架都封裝了Ajax調用,但初學者對於Ajax的原理並不了解,導致在學習時一知半解,為此,我將之前寫的書中的章節發布出來,幫助大家更好的理解和學習前端開發。
Ajax簡介
Ajax的全稱是Asynchronous JavaScript and XML,即異步JavaScript和XML。Ajax最早是由Adaptive Path公司的諮詢顧問Jesse James Garrett在2005年2月提出的,Garrett專門寫了一篇文章來講述Ajax這一新的Web開發方式,文章名為“Ajax: A New Approach to Web Applications”,有興趣的讀者可以從下面的網址處看到這篇文章:
http://www.adaptivepath.com/ideas/essays/archives/000385.php
Garrett將XHTML和CSS、DOM、XML和XSLT、XMLHttpRequest和JavaScript多種技術的綜合應用稱之為Ajax,換句話說,Ajax並不是一種技術,它是多種技術的組合,包括:
使用XHTML和CSS來呈現數據;
使用DOM實現動態顯示和交互;
使用XML和XSLT實現數據交換與操作;
使用XMLHttpRequest實現異步數據的發送與接收;
使用JavaScript將XHTML、DOM、XML和XMLHttpRequest綁定。
實際上,早在Garrett發表文章為Ajax命名之前,Ajax就已經在一些Web系統中應用了。Google是最早採用Ajax的公司之一,它在一些產品中使用了Ajax,如Google Suggest、Google Maps和Gmail等,也正是因為Ajax在這些產品中的成功應用,極大地鼓舞了開發人員在Web系統中使用Ajax的信心,使得Ajax得以迅速推廣。
Ajax為用戶帶來了更好的用戶體驗。在傳統的Web應用程序中,用戶向服務器發送一個請求,然後等待,服務器對用戶請求進行處理,然後返回一個響應。這是一種同步的處理方式,如果服務器處理請求的時間比較長,那麼用戶將不得不長時間的等待,“獃獃地”盯着空白的瀏覽器窗口。☺
傳統的Web應用程序模型和它的同步傳輸機制分別如圖1和圖2所示。
圖1 傳統的Web應用程序模型
圖2 傳統的Web應用程序模型(同步傳輸)
長久以來,我們對這種Web交互模式已經習以為常,以為Web就是這麼用的,直到Ajax的出現。
與傳統的Web應用程序不同,Ajax採用了異步交互機制,從而避免了用戶請求-等待-響應這種交互方式的缺點。Ajax應用程序在用戶和服務器之間引入了一個中間層——Ajax引擎,它是用JavaScript編寫的,在一個隱藏的框架中運行。Ajax引擎負責呈現用戶界面,以及代表用戶與服務器進行交互。Ajax引擎允許用戶與服務器端的Web程序之間的交互異步地進行,這樣用戶就無須“獃獃地”看着空白的瀏覽器窗口和一個沙漏圖標,等待服務器返迴響應頁面了。使用了Ajax的Web應用程序的模型和它的異步傳輸機制分別如圖3和圖4所示。
圖3 Ajax Web應用程序模型
圖4 Ajax Web應用程序模型(異步傳輸)
DOM
DOM是Document Object Model的縮寫,即文檔對象模型,它是W3C組織推薦的處理XML的標準接口。2004年4月7日,W3C組織發布了DOM Level3 Core的推薦標準,有關DOM的技術報告可以在
http://www.w3.org/DOM/DOMTR.html上查看。
DOM是獨立於程序設計語言的,W3C組織以IDL(Interface Definition Language,接口定義語言)的形式定義了DOM中的接口。某種程序語言要實現DOM,需要將DOM接口轉換為本語言中的適當結構,為了保證不同語言的不同DOM之間實現廣泛的兼容,W3C組織在DOM規範的附錄部分提供了Java和ECMAScript這兩種語言的語言綁定。
DOM中的核心概念就是節點。DOM在分析HTML和XML文檔時,將組成HTML和XML文檔的各個部分(元素、屬性、文本、注釋等)映射為一個對象,這個對象就叫做節點。在內存中,這些節點形成一棵文檔樹。整棵樹是一個節點,樹中的每一個節點也是一棵樹(子樹),可以說,DOM就是對這棵樹的一個對象描述,我們通過訪問樹中的節點來存取HTML和XML文檔的內容。
使用DOM,我們不但可以訪問HTML的各個節點,還可以編輯HTML文檔的內容,從而創建動態的頁面。
例如,HTML頁面有一個表格,代碼如例1所示。
例1 顯示圖書信息的表格
<table>
<tbody id="booksBody">
<tr>
<th>書名</th>
<th>作者</th>
</tr>
<tr>
<td>《Java無難事》</td>
<td>孫鑫</td>
</tr>
</tbody>
</table>
如果我們想要為這個表格動態添加一行圖書信息,在JavaScript中可以使用DOM來實現這一功能,代碼如例2所示。
例2 使用DOM動態提交圖書信息
<script type="text/javascript">
var row = document.createElement("tr");
cell = createCellWithText("《Vue.js 3.0從入門到精通》");
//將單元格作為子節點添加到<tr>元素中
row.appendChild(cell);
cell = createCellWithText("孫鑫");
row.appendChild(cell);
//將新創建的錶行添加到<tbody>元素中
document.getElementById("booksBody").appendChild(row);
//定義創建單元格的函數
function createCellWithText(text) {
var cell = document.createElement("td");
var textNode = document.createTextNode(text);
cell.appendChild(textNode);
return cell;
}
</script>
提示: DOM和JavaScript並不是一回事。DOM是面向HTML和XML的API,為文檔提供了結構化的表示。JavaScript是一種語言,它提供了DOM的實現。在JavaScript中,除了可以使用DOM API,還可以使用其他的API。
XMLHttpRequest
XMLHttpRequest對象是整個Ajax技術的核心,正是因為有了這個對象,異步交互才有可能實現。XMLHttpRequest最早是在IE 5中以ActiveX組件的形式實現的,它可以直接向服務器傳輸數據,而不需要由頁面來發送請求,同時它還可以直接從服務器接收響應,而不需要刷新頁面。
IE把XMLHttpRequest實現為一個ActiveX對象,其他的瀏覽器(Firefox、Safari和Opera)則把它實現為一個本地的JavaScript對象。因此,為了兼容不同的瀏覽器,你需要按照例3所示的方式來創建XMLHttpRequest對象。
例3 兼容不同瀏覽器的XMLHttpRequest對象的創建方式
var xmlHttp;
function createXMLHttpRequest() {
if(window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
}
XMLHttpRequest的方法如表1所示。
表1 XMLHttpRequest的方法
方 法 | 說 明 |
abort() | 終止當前請求 |
getAllResponseHeaders() | 以字符串的形式返回所有的響應報頭 |
getResponseHeader(String header) | 獲取指定的響應報頭的值 |
open(String method,String uri) | 建立對服務器的調用。method參數可以是GET、POST或HEAD。url參數可以是相對URL或絕對URL。該方法還有三個可選的參數 |
send(content) | 向服務器發送請求 |
setRequestHeader(String header, String value) | 設置請求的報頭信息。在設置任何報頭之前,必須先調用open()方法 |
XMLHttpRequest的屬性如表2所示。
表2 XMLHttpRequest的屬性
屬 性 | 說 明 |
onreadystatechange | 每個狀態改變時都會觸發這個事件處理器,通常是一個JavaScript函數 |
readyState | 請求的狀態。有5個可能的取值:0(未初始化)、1(請求已建立,但還沒有發送)、2(請求已發送,但還沒有收到響應)、3(正在接收,通常響應中的部分數據已經可用,但還沒有完全接收完畢)、4(響應已完成) |
responseText | 服務器的響應,表示為文本內容 |
responseXML | 服務器的響應,表示為XML。這個對象可以解析為一個DOM對象 |
status | 服務器的HTTP狀態代碼,如200對應OK,404對應Not Found等。僅當readyState值為3或4時,該屬性才可用 |
statusText | HTTP狀態代碼的描述文本,如OK、Not Found等。僅當readyState值為3或4時,該屬性才可用 |
statusText | HTTP狀態代碼的描述文本,如OK、Not Found等。僅當readyState值為3或4時,該屬性才可用 |
我們看一個使用XMLHttpRequest發送請求和接收響應的例子,代碼如例4所示。
例4 使用XMLHttpRequest發送請求和接收響應的例子
var xmlHttp;
if(window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
var email = document.getElementById("email");
var url = validate?email=" + escape(email.value);
xmlHttp.open("GET", url);
xmlHttp.onreadystatechange=handleStateChange;
xmlHttp.send(null);
//處理服務器響應的回調函數
function handleStateChange() {
//判斷響應是否完成
if(xmlHttp.readyState == 4) {
//判斷響應是否成功
if(xmlHttp.status == 200) {
alert(xmlHttp.responseText);
}
}
}
XMLHttpRequest Level2
XMLHttpRequest API使得Ajax技術的實現成為了可能,作為XMLHttpRequest的改進版, XMLHttpRequest Level 2在功能上有了很大的改進,主要包括:
- 跨源XMLHttpRequest
- 進度事件(Progress event)
跨源HTTP請求包括一個Origin頭部,它為服務器提供HTTP請求的源信息。頭部由瀏覽器保護,不能被應用程序代碼更改。
使用跨源XMLHttpRequest可以構建基於非同源服務的Web應用程序。
1、新增事件
事件名稱 | 說明 |
loadstart | 當請求開始 |
progress | 在發送和加載數據期間 |
abort | 請求已被終止。如調用abort()方法 |
error | 當請求已失敗 |
load | 當請求已成功完成 |
timeout | 在請求完成之前指定的超時值到了 |
loadend | 當請求已完成(無論成功或失敗) |
2、檢測瀏覽器對XMLHttpRequest2的支持
var xhr = new XMLHttpRequest() ;
if (typeof xhr.withCredentials === undefined){
// 您的瀏覽器不支持跨源的XMLHttpRequest
}
3、示例
<!DOCTYPE html>
<html>
<head>
<meta charset="GBK">
<title>跨源上傳</title>
<script>
var xmlHttp;
function checkSupport(){
xmlHttp = window.XDomainRequest ? new XDomainRequest : new XMLHttpRequest;
if(typeof xmlHttp.withCredentials == undefined) {
alert("您的瀏覽器不支持跨源的XMLHttpReqeust");
}
}
checkSupport();
function upload(){
xmlHttp.onprogress = function(e){
var radio = e.loaded / e.total;
displayProgress(radio + "% 上傳");
}
xmlHttp.onload = function(e){
displayProgress(xmlHttp.responseText);
}
xmlHttp.onerror = function(e){
displayProgress("出錯了");
}
var targetLocation = "http://example.com:8080/upload.jsp";
var data = document.getElementById("data").value;
xmlHttp.open("POST", targetLocation, true);
xmlHttp.send(data);
}
function displayProgress(info){
document.getElementById("state").innerHTML = info;
}
</script>
</head>
<body>
<p>
上傳消息:
<input type="text" id="data" placeholder="輸入要上傳的數據">
<button id="sendButton" onclick="upload();">發送數據</button>
</p>
<p>
狀態:<span id="state">準備</span>
</p>
</body>
</html>
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/230900.html