一、簡(jiǎn)介
1、ajax是Asynchronous Javascript and XML的縮寫,意思是執(zhí)行異步的網(wǎng)絡(luò)請(qǐng)求
2、我們會(huì)發(fā)現(xiàn)使用form表單submit按鈕提交表單的時(shí)候,網(wǎng)頁(yè)會(huì)有執(zhí)行刷新操作,在新頁(yè)面告知操作結(jié)果,而ajax技術(shù)可以使得向服務(wù)器請(qǐng)求數(shù)據(jù)的時(shí)候無需卸載頁(yè)面,得到更好的體驗(yàn)
3、ajax的核心是XMLHttpRequest對(duì)象,它實(shí)現(xiàn)了異步方式從服務(wù)器獲取數(shù)據(jù),也就是用XHR對(duì)象獲取到服務(wù)器的數(shù)據(jù),再使用DOM將數(shù)據(jù)更新到頁(yè)面中
4、雖然ajax名字中包含了XML,但是他只是一種通信手段,與具體數(shù)據(jù)格式?jīng)]有關(guān)系,因?yàn)楫?dāng)時(shí)主流使用XML作為前后臺(tái)通信數(shù)據(jù)的格式,所以名字中使用了XML;而現(xiàn)在主要使用的都是JSON格式的字符串
二、XMLHttpRequest對(duì)象
ajax的實(shí)現(xiàn)流程如下:
- 創(chuàng)建XHR對(duì)象
- 調(diào)用open()方法,創(chuàng)建請(qǐng)求
- 調(diào)用send()方法,發(fā)送請(qǐng)求
- 捕獲請(qǐng)求狀態(tài),判斷請(qǐng)求結(jié)果
- 獲取數(shù)據(jù)庫(kù)返回的數(shù)據(jù)
1、創(chuàng)建XHR對(duì)象
XHR對(duì)象首次實(shí)現(xiàn)是在ie5上,當(dāng)時(shí)使用的是ActiveX
對(duì)象,所以XHR下ie上有兩個(gè)版本的實(shí)現(xiàn)方式,ie7以下的ActiveX
對(duì)象與ie7及以上的XHR對(duì)象,其余瀏覽器統(tǒng)一都是使用的XHR對(duì)象
所以創(chuàng)建對(duì)象的時(shí)候需要有兼容性寫法
if(window.XMLHttpRequest){
var request = new XMLHttpRequest();
}else{
//這是ie7以下的寫法
var request = new ActiveXObject("Microsoft.XMLHttp");
}
??????????
2、調(diào)用open()方法
request.open(method,url,boolean);
open()方法接收3個(gè)參數(shù)
- method:數(shù)據(jù)提交方式,字符串形式,可以使用"get"或"post"
- url:請(qǐng)求對(duì)象地址,字符串表示(get方式與post方式有差異)
- boolean:true(默認(rèn))表示異步請(qǐng)求,false表示同步請(qǐng)求(相信使用ajax都是為了異步的,所以這里就用true,或者不填寫)
get方式請(qǐng)求
使用get方式提交數(shù)據(jù)時(shí)需要將提交內(nèi)容以固定的格式附加在URL后面,格式如下:
url = "地址 ? name1=value1 & name2=value2";
//獲取到用戶名及密碼的輸入框
var username = document.getElementById("username");
var passwd = document.getElementById("passwd");
//將輸入內(nèi)容附加在URL后面
var url = "php/get.php?username="+username.value+"&passwd="+passwd.value;
//調(diào)用open()方法
request.open("get",url,true);
post方式請(qǐng)求
使用post方式提交數(shù)據(jù),提交內(nèi)容是作為send()方法的參數(shù)提交的,所以URL后面無需附加參數(shù)
//獲取到用戶名及密碼的輸入框
var username = document.getElementById("username");
var passwd = document.getElementById("passwd");
//將輸入內(nèi)容附加在URL后面
var url = "php/post.php";
//調(diào)用open()方法
request.open("post",url,true);
注意:因?yàn)橐呀?jīng)不再使用form表單,所以后臺(tái)無法再使用name屬性獲取數(shù)據(jù),之前定義在form表單name屬性中的內(nèi)容現(xiàn)在就是在name1=value1
中的name1
中,相應(yīng)的,post方式就是下文中的postbody中的name1
3、調(diào)用send()方法
request.send(postbody);
send()方法接收1個(gè)參數(shù)
- postbody:字符串形式,填入需要提交的數(shù)據(jù);如果沒有提交的數(shù)據(jù),可以填入
null
get方式請(qǐng)求
因?yàn)間et方式下的數(shù)據(jù)已經(jīng)附加在URL后面提交,所以這里一般填入null
post方式請(qǐng)求
數(shù)據(jù)的格式如下:
postbody = "name1=value1 & name2=value2";
//獲取到用戶名及密碼的輸入框
var username = document.getElementById("username");
var passwd = document.getElementById("passwd");
//將輸入內(nèi)容附加在URL后面
var postbody = "username="+username.value+"&passwd="+passwd.value;
//調(diào)用send()方法
request.send(postbody);
注意1:此處用post方式提交數(shù)據(jù)與用form表單提交畢竟有所不同,服務(wù)器會(huì)需要程序來讀取并解析原始數(shù)據(jù),所以我們需要使用XHR來模仿表單提交:
//將Content的頭部信息重新設(shè)置
//定義表單提交時(shí)的內(nèi)容類型,并以適當(dāng)類型創(chuàng)建一個(gè)字符串 request.setRequestHeader("Content-Type","application/x-www/form-unencoded");
注意2:這個(gè)方法只能加在open()方法之后,send()方法之前
//實(shí)際使用方法
var username = document.getElementById("username");
var passwd = document.getElementById("passwd");
var url = "php/post.php";
request.open("post",url,true);
//放置的位置一定在這里
request.setRequestHeader("Content-Type","application/x-www/form-unencoded");
var postbody = "username="+username.value+"&passwd="+passwd.value;
request.send(postbody);
4、捕獲請(qǐng)求狀態(tài),判斷結(jié)果
send()方法調(diào)用后,請(qǐng)求就會(huì)被提交到服務(wù)器;多數(shù)情況下,我們會(huì)發(fā)送異步請(qǐng)求先檢查請(qǐng)求過程當(dāng)前的活動(dòng)階段,再判斷請(qǐng)求是否返回成功
XHR對(duì)象相關(guān)屬性:
- readyState:請(qǐng)求 /相應(yīng)過程的當(dāng)前活動(dòng)階段
- responseText:作為響應(yīng)主體被返回的文本
- responseXML:如果相應(yīng)的內(nèi)容類型是text/xml或者application這個(gè)屬性中將保存著響應(yīng)數(shù)據(jù)的XMLDOM文檔
- status:相應(yīng)的HTTP狀態(tài)
- statusText:HTTP狀態(tài)說明
我們利用原生的onreadystatechange事件來監(jiān)聽readyState變化
readyState返回值如下:
只要readyState的值有一個(gè)值變?yōu)榱硪粋€(gè)值,就會(huì)觸發(fā)一次
onreadystatechange
事件,可以利用此事件來返回監(jiān)聽到的請(qǐng)求/響應(yīng)過程狀態(tài)值
我們關(guān)心的是readyState值為4的情況,因?yàn)檫@是代表所有數(shù)據(jù)已經(jīng)準(zhǔn)備就緒;同時(shí)如果status返回的是200,那么可以確定該次去請(qǐng)求/響應(yīng)過程全部完成
status返回值如下:
注意:這里不要使用statusText去判斷,因?yàn)樵撝翟诳鐬g覽器時(shí)不可靠
最后的返回結(jié)果,不管是什么類型內(nèi)容,都會(huì)被保存在responseText中
監(jiān)聽代碼如下:
//監(jiān)聽readyState狀態(tài)與status返回值
request.onreadystatechange = function () {
if(request.readyState == 4 && request.status == 200){
alert(request.responseText);
}
}
綜上所述的內(nèi)容,就是整個(gè)ajax請(qǐng)求的全部流程,我們?cè)趈s中最后拿到的就是后臺(tái)返回的responseText,只里面保存的一般來說是JSON格式的字符串,我們可以將其轉(zhuǎn)換成數(shù)組或者對(duì)象后提取其中的鍵值對(duì)
三、封裝使用
以下代碼是將上述的過程進(jìn)行的封裝,使得使用時(shí)只要調(diào)用函數(shù)并在回調(diào)函數(shù)中實(shí)現(xiàn)功能就可以了
<script>
/*
* method是請(qǐng)求方式
* url是網(wǎng)絡(luò)請(qǐng)求的地址
* postboidy是post方式請(qǐng)求時(shí)的提交數(shù)據(jù)
* successCallback是請(qǐng)求成功的函數(shù)
* errorCallback是請(qǐng)求失敗的函數(shù)
*/
function request (method,url,postbody,successCallback,errorCallback) {
//創(chuàng)建一個(gè)請(qǐng)求對(duì)象
if(window.XMLHttpRequest){
var request = new XMLHttpRequest();
}else{
var request = new ActiveXObject("Microsoft.XMLHttp");
}
if(arguments[0]=="POST"){
//創(chuàng)建請(qǐng)求
request.open(method,url,true);
//設(shè)置上傳類型
request.setRequestHeader("content-type","application/x-www-form-urlencoded");
}else if(arguments[0]=="GET"){
request.open(method,url,true);
}
//發(fā)送請(qǐng)求
request.send(postbody);
//狀態(tài)監(jiān)聽
request.onreadystatechange = function () {
if(request.readyState ==4 && request.status == 200){
//請(qǐng)求成功的回調(diào)函數(shù)
if(successCallback){
successCallback(request.responseText);
}
} else if (request.readyState == 4 && request.status != 200) {
//請(qǐng)求失敗的回調(diào)函數(shù)
if(errorCallback){
errorCallback(request.statusText);
}
}
}
}
</script>
使用方法舉例:
下面定義了一個(gè)簡(jiǎn)單的表單提交用戶名和密碼,使用回調(diào)函數(shù)拿到后臺(tái)返回的JSON串后,轉(zhuǎn)換成對(duì)象再取出其中的信息,告知用戶是登陸成功還是失敗
//html部分
//調(diào)用封裝好的函數(shù)
<script src="request.js"></script>
<div class="form">
<input type="text" id="username">
<input type="password" id="passwd">
<button id="loginBtn">登錄</button>
</div>
//js部分
<script>
var username = document.getElementById("username");
var passwd = document.getElementById("passwd");
var loginBtn = document.getElementById("loginBtn")
loginBtn.onclick = function () {
//設(shè)置請(qǐng)求地址及提交內(nèi)容
var url = "login.php";
var postbody = "username="+username.value+"&passwd="+passwd.value;
//發(fā)起ajax請(qǐng)求,并使用回調(diào)函數(shù)實(shí)現(xiàn)功能
request("POST",url,postbody,function (resText) {
//把json格式的字符串轉(zhuǎn)換成對(duì)象
var obj = JSON.parse(resText);
alert(obj.msg);
});
}
</script>
//php部分login.php
<?php
//從請(qǐng)求中獲取用戶名和密碼
$username = $_POST["username"];
$passwd = $_POST["passwd"];
//連接服務(wù)器
@$mysqli = new mysqli("localhost","root","","user");
$mysqli->query("set names utf8");
//查詢語句
$sql = "SELECT * FROM user WHERE username='$username' AND passwd='$passwd'";
//數(shù)據(jù)庫(kù)執(zhí)行查詢
$result = $mysqli->query($sql);
//判斷查詢結(jié)果是否有值,并定義返回字符串
//echo出來的就是返回前端的數(shù)據(jù)
if($result->num_rows > 0){
echo '{"errorcode":0,"msg":"登陸成功"}';
}else{
echo '{"errorcode":1,"msg":"用戶名或密碼錯(cuò)誤"}';
}
//關(guān)閉服務(wù)器
$mysqli->close();
?>