在介紹ajax之前,博主想先介紹一些關于HTTP協(xié)議的知識.
例如百度的網(wǎng)址: http://www.baidu.com
我們可以看到,在整個域名地址的開頭,有一個http協(xié)議,類似的還有https協(xié)議.
1.什么是Ajax?
Ajax全稱:Asynchronous JavaScript+XML
它不是一個技術,實際上是幾種技術的結合,合在一起就成了一個功能強大的新技術.
主要作用是在無刷新頁面的情況下向服務器讀取數(shù)據(jù),可以應用在用戶登入,在線聊天室等地方
2.編寫一個Ajax
Ajax的核心實際是一個XMLHttpRequest對象,這個對象在目前的所有瀏覽器都支持,只是IE6 和 IE5的寫法不一樣而已驴娃。既然是一個對象的話,就存在它內置的屬性和方法.
1.創(chuàng)建XMLHttpRequest對象
首先,我們要先創(chuàng)建XMLHttpRequest這么一個對象.
出于兼容性考慮,為了照顧IE5,6在這呢,我做了一個兼容性的處理
var xhr = window.XMLHttpRequest ? XMLHttpRequest( ) : ActiveXObject("Microsoft.XMLHTTP");
XMLHttpRequest
對象實際也是屬于window的,所以出于嚴謹并避免不必要的麻煩,還是window.XMLHttpRequest
比較好.
XMLHttpRequest()
各大瀏覽器都支持
ActiveObject("Microsoft.XMLHTTP")
是IE5.6的寫法
2.連接到服務器
當xhr對象創(chuàng)建完畢之后,我們要使用一個open()的方法來連接到服務器
先來看下寫法:
xhr.open('GET', 'msg.txt', true)
open()方法中有3個參數(shù),我們分別來看下什么意思
第一個參數(shù):
請求方法,一般是get或post
第二個參數(shù):
請求是url
第三個參數(shù):
是否為異步,默認true是異步,false是同步
3.監(jiān)聽請求狀態(tài)
使用onreadystatechange方法,來監(jiān)聽請求狀態(tài).
請求狀態(tài)xhr.readyState的值保存了xhr的狀態(tài)
然而xhr一共有5種狀態(tài),分別是:
- 0 未初始化鹉胖。對象new出來了肮疗,但是還沒有調用open方法
- 1 啟動播聪。 已經(jīng)調用open象对,但是還沒有調用send方法
- 2 發(fā)送削彬。 已經(jīng)send方法乌妙,但是還沒有接收到相應
- 3 接收。 已經(jīng)開始接收數(shù)據(jù)替蛉,但是還沒有完全接收贯溅。
- 4 完成。 已經(jīng)完全接收數(shù)據(jù)躲查。
我們主要監(jiān)聽的的第5種狀態(tài),也就是完全接收數(shù)據(jù)的狀態(tài).
注:xhr.readyState==4只是表示接收數(shù)據(jù)完成,可以對數(shù)據(jù)進行處理了,此時還得再做一個判斷看看服務器是否響應成功,也就是判斷xhr.status是否為200,200表示成功,304雖然也表示成功,但是有緩存.
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200||xhr.status==304){
onSuccess(xhr.responseText);
}else{
if(typeof onFail=="function"){
onFail(xhr.status);
}
}
}
xhr.responseText指的是ajax向服務器請求之后返回的請求結果.
4.發(fā)送請求
使用xhr.send()方法來向服務器發(fā)送請求
send()方法內也可以傳遞參數(shù),當使用get請求時,只要傳遞null就行了
(若是使用post請求方式的時候,()內可以傳入一個數(shù)據(jù)參數(shù)data,后面會提到)
xhr.send(null)
通過以上四個步驟,我們已經(jīng)會簡單的使用ajax,但是在實際運用中,不可能要用到ajax的時候就再寫一遍,那樣很沒有效率,所以我們可以將整段ajax代碼封裝到一個js代碼中,在我們每次要用到ajax的時候,只需要調用這段js代碼就可以了.
如下,我將以上的四個步驟封裝到了一個myAjax對象中,這個對象中提供了倆個方法,一個是針對get調用,一個是針對post調用,倆個方法異曲同工,只不過在參數(shù)的使用上有一些的不同.具體代碼如下:
文件名: myAjax.js
var myAjax = {
/**
* 負責get請求
* @param url url地址
* @param onSuccess ajax請求成功時候的回調
* @param onFail ajax請求失敗時候的回調
*/
get:function (url,onSuccess,onFail) {
if(!(typeof onSuccess=="function")) return;
var xhr = XMLHttpRequest ? new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('GET',url);
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200||xhr.status==304){
onSuccess(xhr.responseText);
}else{
if(typeof onFail=="function"){
onFail(xhr.status);
}
}
}
};
xhr.send(null);
},
/**
* 負責get請求
* @param url url地址
* @param data 請求的數(shù)據(jù)
* @param onSuccess ajax請求成功時候的回調
* @param onFail ajax請求失敗時候的回調
*/
post:function (url,data,onSuccess,onFail) {
if(!(typeof onSuccess=="function")) return;
var xhr = XMLHttpRequest ? new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('POST',url);
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200||xhr.status==304){
onSuccess(xhr.responseText);
}else{
if(typeof onFail=="function"){
onFail(xhr.status);
}
}
}
};
//在發(fā)送請求之前必須添加這個請求頭,表示表單數(shù)據(jù)進行url編碼
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send(data);
}
}
};
這樣當我們要用到ajax對象的時候,引用這段js代碼就ok了.
例:
編寫一個剪短的登入程序,當用戶輸入的用戶名和密碼和后臺設置的一樣,即顯示登入成功.
1.編寫一段php代碼:
文件名: data.php
<?php
$name = $_POST["name"];
$age = $_POST["pwd"];
header('Content-type:text/html; charset="UTF-8"');
header("Access-Control-Allow-Origin:*");
if($name == "李四"&&$pwd=="123456"){
echo $name . "登入成功" ;
}else{
echo $name . "登入失敗";
}
?>
2.HTML代碼
<form action="data2.php" method="post" id="form1" enctype="application/x-www-form-urlencoded">
<input type="text" name="name">
<input type="text" name="pwd">
<input type="submit" value="登錄">
</form>
3.引入ajax.js并編寫js代碼
<script type="text/javascript" src="myAjax.js"></script>
<script>
var form1 = document.querySelector('#form1');
form1.onsubmit=function (e) {
e.preventDefault();//阻止事件默認行為
var msg = "name=" + this.name.value+'&age="+this.age.value;
myAjax.post('data2.php',msg,function (result) {
console.log(result);
})
}
</script>
同源
通過博主上面的描述,相信大家對ajax都有了一定的了解,那么ajax這么牛能夠使Web頁面不用打斷交互流程進行重新加載它浅,就可以動態(tài)地更新,就沒有什么限制嗎?答案是有的,ajax訪問網(wǎng)頁的時候,ajax的地址,必須和當前頁面同源,否則ajax就不能訪問.
那么這里就要介紹一下同源.
在頁面的地址欄里,我們經(jīng)常可以看到我們輸入的地址,都有一些相似之處,簡單來說,一個網(wǎng)頁的地址主要有這樣幾個組成部分:
協(xié)議://域名:端口號/資源路徑?查詢參數(shù)
https://www.baidu.com/s?ie=UTF-8&wd=王
那么只要倆個網(wǎng)址的 協(xié)議 域名 端口號 三個部分相同,這倆個網(wǎng)址就同源.
如:同源
? http://www.baidu.com
? http://www.baidu.com/abc/a.html
? 不同源:
? http://www.baidu.com
? https://www.baidu.com/abc/a.html
不受同源策略的影響有:
1.img標簽加載圖片
2.script標簽加載js文件
打破同源
現(xiàn)在主要是用倆種方式來打破同源,一直是利用jsonp,還有一種是服務器打破同源
1.jsonp
jsonp: json padding的簡稱,實際就是把json數(shù)據(jù)偽造為一個合理的js代碼.
我們在正常讀取json數(shù)據(jù),得通過ajax來從服務器讀取,但對于一些不同源的json數(shù)據(jù),我們就無法正常讀取,所以這時可以采用一個投機取巧的辦法吧,就是把json數(shù)據(jù)偽造為一個合理的js代碼,這樣就能通過調用js代碼來成功讀取json數(shù)據(jù),如看下面的例子:
<script>
function foo(obj){
console.log(obj)
}
</script>
<script type= "text/script" src= "data.json"></script>
data.json:
foo({
name:'王先生'
})
將json數(shù)據(jù)用一個foo的函數(shù)封裝起來,只要在要讀取json數(shù)據(jù)的時候將json文件用script標簽來引用,并通過foo函數(shù)調用就可以了.
2.服務器打破同源
就像前面說的,判斷是否同源只要看協(xié)議域名端口號三個地方相同不相同,要是相同的話就是同源,我們的ajax就可以訪問到.那么如果我們將服務器端口設置一下,也就是直接在我們的php文件中修改
在php文件的判斷之前加上:
// *代表的就是所有域名都可以訪問
header("Access-Control-Allow-Origin:*");
encodeURIComponent編碼
其實每個漢字都有對應的URI編碼,window提供了一個全局的方法encodeURIcomponent(),將中文轉換為URI編碼
一個中文由3個%號組成,如:
var name = encodeURIComponent('李四');
console.log(name);
=>%E6%9D%8E%E5%9B%9B
后文
Ajax實際就是通過get或者post方法在js中從php文件或者json文件讀取到數(shù)據(jù),然后在js中對這些數(shù)據(jù)進行操作.在實際的開發(fā)中,我們看到頁面上的很多圖片信息或者產(chǎn)品信息,都是通過Ajax讀取數(shù)據(jù)然后添加到頁面中.
另外,要是有小伙學過JQuery的話,會知道JQuery有它內置的Ajax,我們可以直接利用$.get(url,function(result){ })
來讀取數(shù)據(jù).