Ajax的使用以及跨域(上)
Ajax相信大家都聽說過,接下來這幾篇文章就來說說關於Ajax的一些知識,從而也順道引出來在實際工作過程中經常使用的一下技術:跨域。
首先我們先來看Ajax,Ajax簡單的來說,就是一個非同步的javascript請求,用來獲取後臺服務端的資料,為什麼要非同步的呢?很簡單,因為獲取後臺網路資料是需要時間的,如果同步的話,將會講當前介面卡住,造成非常不友好的使用者體驗。
在元素JS中來實現Ajax主要的類就是XMLHttpRequest,它的使用一般有四個步驟:
1、 建立XMLHttpRequest物件
2、 準備傳送網路請求
3、 開始傳送網路請求
4、 指定回撥函式
沒錯,就是這麼簡單的四個步驟,下面我們就通過程式碼來將這四個步驟實現出來。
第一步,建立XMLHttpRequest物件
var xhr = new XMLHttpRequest();
第二步:準備傳送網路請求
xhr.open('get','./01check.php?username='+uname+'&password='+pw,true)
呼叫open方法,這裡面有三個引數,第一個引數代表的這個Http請求是以get方式還是post方式,如果是get請求,則如果有引數的話,則需要將引數跟在url的後面,而如果是post請求,引數應該跟在請求體中。
第二個引數就是這個Http請求的url地址。這個url地址後面是否有?加引數,得取決於第一個引數是get還是post
第三個引數代表這個Http請求是同步的還是非同步的。false代表同步,true代表非同步。這個引數一般都是寫true,因為誰都不想在網路請求的時候,將這個網頁卡住吧?不過對於學習來說的話,我們等等可以測試一下false的效果。
第三步:開始傳送網路請求
xhr.send(null);
呼叫send方法,傳遞一個null。需要注意的是,如果你在第二步的請求方式為get的話,那麼這裡傳null,如果在第二步的請求方式為post的話,這裡就需要傳入你所需要傳遞給伺服器的引數了。因為之前我們說過,post請求的引數並不是跟在url後面的,而是跟在請求體中,而send方法中的引數就是會被設定到請求體中。因此,對於post請求,需要在這裡傳遞引數。如:
var param = 'username='+uname+'&password='+pw;
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(param);
需要注意的是,如果使用post請求,並且又有引數的話,那麼對於xhr就必須設定請求頭資訊,否則服務端接受不到引數。這個寫法都是固定的,如有需要直接複製即可,不需要背。
第四步,指定回撥函式,xhr.send方法呼叫完之後,http請求就傳送出去了。由於在第二步中,我們設定了請求為非同步請求,非同步請求不能直接獲得結果,只能通過監聽回撥的方式來得到響應資料。
xhr.onreadystatechange
= function(){
if(xhr.readyState
== 4){
if(xhr.status
== 200){
alert(xhr.responseText);
}
}
}
上訴程式碼的4和200代表的正常得到資料,伺服器響應正常,那麼這時候我們就可以通過xhr.responseText來獲取到伺服器給我們返回的資料了。
這裡給出readyState和status的常用值代表含義的對應關係
好,通過上訴步驟,我們就能實現Ajax來完成非同步請求了。完整的程式碼如下:
get請求:
<script
type="text/javascript">
window.onload
= function(){
var btn
= document.getElementById('btn');
btn.onclick = function(){
var uname
= document.getElementById('username').value;
var pw
= document.getElementById('password').value;var
xhr = new
XMLHttpRequest();
xhr.open('get','./01check.php?username='+uname+'&password='+pw,true);xhr.send(null);xhr.onreadystatechange =
function(){
if(xhr.readyState ==
4){
if(xhr.status ==
200){
var data
= xhr.responseText;
}
}
}
}
}
</script>
post請求:
<script
type="text/javascript">
window.onload
= function(){
var btn
= document.getElementById('btn');
btn.onclick = function(){
var uname
= document.getElementById('username').value;
var pw
= document.getElementById('password').value;var
xhr = new
XMLHttpRequest();
xhr.open('post','./01check.php',true);
var param = 'username='+uname+'&password='+pw;
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(param)xhr.onreadystatechange =
function(){
if(xhr.readyState ==
4){
if(xhr.status ==
200){
var data
= xhr.responseText;
}
}
}
}
}
</script>
關於原生的Ajax請求,還有一點需要說明的就是在第二個步驟設定的同步還是非同步的標識位。也就是xhr.open方法的最後一個引數,這個值一般都是true,但是總有人愛裝牛角尖,就會問如果是false會怎樣?
前面已經說過了,這個值true代表是非同步請求伺服器的資料,false代表同步請求伺服器的資料。如果是同步請求,那麼在xhr獲取到資料之前,整個瀏覽器都是卡在send方法等待資料返回,所以此時使用者操作介面是沒有任何效果的,按鈕點選不了,頁面也滾動不了,體驗非常的差。這裡需要說明的是,如果真有人把這個引數寫成false的話,那麼在第四步中獲取資料的方式將會有所改變。如下:
<script
type="text/javascript">
window.onload
= function(){
var btn
= document.getElementById('btn');
btn.onclick = function(){
var uname
= document.getElementById('username').value;
var pw
= document.getElementById('password').value;var
xhr = new
XMLHttpRequest();
xhr.open('get','./01check.php?username='+uname+'&password='+pw,false);xhr.send(null);if(xhr.readyState ==
4){
if(xhr.status ==
200){
var data
= xhr.responseText;
}
}
}
}
</script>
注意到沒有,如果是同步請求的話,那麼我們就不需要監聽onreadystatechange方法。因為xhr在send方法呼叫的時候,是一直卡在這個方法中的。一旦這個方法結束,那麼xhr就已經成功的訪問到伺服器的資料了,不需要做readystatechange的監聽。換句話說,這時候readystatechange也監聽不到了。因為xhr.onreadystatechange = function(){}這行程式碼是在xhr.send之後呼叫的,對於同步方法來說,send方法中xhr.readystate已經發生了變化,最後變為4之後才跳出send方法繼續向下執行。
最後,還需要講一個稍微不太重要的東西,就是XMLHttpRequest的建立對於低版本的IE需要做相容。因為低版本的IE可能沒有XMLHttpRequest這個物件。做法如下:
var xhr
= null;
if(window.XMLHttpRequest){ //能力測試
xhr = new
XMLHttpRequest();//標準}else{
xhr = new
ActiveXObject("Microsoft.XMLHTTP");
}
好,到目前為止呢,我們就講了關於Ajax在原生js下的使用方式和注意事項,總結來說有以下幾點:
1、 XMLHttpRequest物件建立的相容處理
2、 get請求post請求在程式碼上有什麼差異
3、 同步和非同步的影響,以及同步和非同步獲取資料的差異。
其實在實際開發中,我們比較少自己使用原生的js程式碼來實現Ajax,而是使用第三方庫,比如jQuery,那麼jQuery如何來使用Ajax,我們自己能不能封裝一個類似jQuery一樣的Ajax呼叫方式呢?我們下一篇文章再來說明一下。