淺談js之ajax


0x00:什么是Ajax?

  Ajax是Asynchronous Javascript And Xml 的縮寫(異步javascript及xml),Ajax是使用javascript在瀏覽器后台操作HTTP和web服務器進行數據交換(用戶不知道也感覺不出來,就跟桌面應用程序似的進行數據交互),它不會導致頁面重新加載,這樣才有更好的用戶體驗。

  Ajax是基於以下開放標准:

  • javascript(DOM)
  • css
  • html
  • xml(json)

通俗的說就是使用了javascript(DOM)的XMLHttpRequest對象(ajax核心API也是瀏覽器的http API)及后續一系列的操作(發送和接收操作),接收來自服務器xml(json)等數據格式的數據,用html和css來顯示出來。所以它們只是組合出來的一種新的技術。

歷史什么的我就不介紹了。

0x01:怎樣使用Ajax?

  001:實例化一個XMLHttpRequest對象

  var xhr = new XMLHttpReques();

就是這么簡單。一般不用考慮兼容性,如果你想讓每一用戶都能享受到ajax帶來的福利。你還要考慮我們IE5,6的朋友(現在應該用的不多了吧,具體我也不知道);

你可以定義一個實例化這個對象的函數:

function createXHR() {

    if(window.XMLHttpRequest) {
        return new XMLHttpRequest();
    } else if(window.ActiveXObject) {
        return new ActiveXObject(Microsoft.XMLHTTP);
    }
}

這就兼容一切瀏覽器了。

002:發送請求

    實例化對象后,就要發送請求了,要使用XMLHttpRequest對象的open()和send()方法及可選setRequestHeader()方法(請求頭設置)。

    首先來說open()方法。它可以接受三個參數,第一個參數是要發送的請求的類型(即GET,POST等),第二個參數是請求的URL(網址)(即服務器上文件的地址,但不能跨域請求),第三個參數是一個布爾值(true表示異步,false表示同步)。

    細節

      the first argument:第一個參數GET,POST等是不區分大小寫的,但是通用的做法是都用大寫。

        那什么時候用GET,什么時候用POST呢?

        GET簡單說就是向服務器請求查詢資源時用,請求不對服務器有任何副作用,是冪等的(即對同一url多次請求應該返回相同的結果)

        具體以下是GET請求的特點,你可以根據這些特點來使用

          1.GET請求的響應可以被瀏覽器緩存

          2.GET請求有長度限制(具體跟瀏覽器和服務器自身設置有關一般可以2k-8k) 

          3.GET請求可以在歷史記錄中查看,(如果發送了敏感數據,別人通過查看你的歷史記錄就能看見)

          4.GET請求可以保存為書簽

          5.GET請求只有請求頭,沒有主體,要設置查詢字符串參數,首先要進行編碼,然后把數據放在url后面,用?把地址和查詢參數隔開,

           查詢參數之間用&隔開例如:www.123.com/aa.php?name=‘wy’l&id=001;url地址欄所以也不能發送敏感數據,用戶能看見了。

        POST是向服務器發送要處理的數據時用

        具體以下是POST請求的特點。

          1.一般不對請求的數據的長度進行限制

          2.瀏覽器不進行緩存文件、數據,無法使用緩存文件等

          3.數據在主體中,相對GET安全點,一般用戶看不見,要是用工具那就另說了,get可能造成CSRF攻擊

          4.發送包含未知字符的用戶輸入時,POST 比 GET 更穩定也更可靠

根據這些特點你就知道該什么時候用GET和POST。

       the second argument:第二個參數,需要注意的是,不能進行跨域請求。什么是跨域呢,就是當兩個url中只要

       其中一項不同就是跨域,協議,域名,端口不同就是跨域,具體如下截圖,看懂就明白了。

截圖來自:http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html

      the third argument:第三個參數是可以省略的,那就默認異步(true),異步和同步在不同的地方解釋會有不同,這里是的意思是,同步的話會阻塞javascript的執行,就是說在調用send()方法后,瀏覽器就會在這個地方停止后面的代碼執行,一直到服務器響應,才再往下執行后面的代碼,如果用異步的話,javascript就會在調用了send()方法后,不會等待服務器的響應,繼續執行下面的代碼,但是你也不能不管了吧,這里就會說到下面要講的要進行事件監聽,當你服務器有響應了,我再去操作你的數據等操作。

說了半天也沒有說代碼是怎么樣的:

//GET請求
xhr.open("GET","www.123.com/bb.php")
xhr.open("GET","www.123.com/bb.php?a=2&b=3")//如果你要加上查詢數據的話
//POST請求
xhr.open("POST","www.123.com/aa.php")

 

在說send()方法之前還要說,請求頭的設置,如果是GET請求,這一步可以沒有,但是要是POST表單編碼請求必須要設置“Content-Type”頭來指定請求的主題的MIME類型(就是告訴服務器我給的是什么類型的數據)值為:application/x-www-form-urlencoded。它的值還有值可以是application/json,text/plain,text/html,text/xml等,有時候XMLHttpRequest對象會自動識別你發送數據的類型,所以你也可以沒有,但是最好設置上。其他的如果你有特殊需要你就設置;有一些頭是你不能自己設置,如Content-Length,Date,Referer,User-Agent等,除了這些你都可以自己設置,不需要的瀏覽器就發送自己默認的請求頭。如果對相同的頭調用setRequestHeader()多次,新值不會取代之前的值,而是HTTP請求頭包含這個頭的多個副本或者這個頭將指定多個值。

設置請求頭用setRequestHeader()方法。一定要注意了,必須在調用open()方法之后,並且在調用send()方法之前調用setRequestHeader()方法。

post用:

xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");//表單編碼的請求

現在真是說send()方法。先說GET下的send(),

xhr.send();//可以這樣
xhr.send(null);//也可以這樣,傳遞一個null,最好設置為null,說有些瀏覽器不設置為null會報錯,所以推薦這樣

POST:

xhr.send(msg)//請求的主體要發送內容

之后一次請求就這樣被發送到服務器了,接下來就等着響應數據了,來進一步進行操作了。

003:等待響應

可以使用XMLHttpRequest對象的一些屬性和方法來檢測服務器的響應。

    首先說readyState屬性和readystatechange事件。

 redayState屬性表示請求或響應過程處於當前的什么階段了,它是用一個整數表示的0-4。我看見關於這個狀態的每個整數代表的什么狀態,說的稍微有點混亂或者說不太明確。我就測試了一下post下的情況,先上測試代碼:

window.addEventListener("load",function() {
var request = new XMLHttpRequest();
console.log("初始化對象時--" + request.readyState);//0
request.onreadystatechange = function() {
    console.log("事件--" + request.readyState);//打印每次觸發事件時readyState的狀態
    console.log("服務器--" + request.status);
    if(request.readyState === 2) {
        console.log(request.getResponseHeader("Content-Type"));
    }
    if(request.readyState === 3) {
        console.log(request.responseText);
    }
    if(request.readyState === 4 && request.status == 200) {
            console.log(request.getResponseHeader("Content-Type"));
            // console.log(JSON.parse(request.responseText));
            console.log(request.responseText);
    }
}
console.log("調用open之前--" + request.readyState);//0
console.log("服務器--" + request.status);
request.open("POST","./test.php",true);
console.log("調用open之后--" + request.readyState);//1
console.log("服務器--" + request.status);
request.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");
console.log("設置頭之后--" + request.readyState);//1
console.log("服務器--" + request.status);
request.send('aa="aadfd"');
console.log("調用send之后" + request.readyState);//1
console.log("服務器--" + request.status);
},false);
<?PHP
header("Content-Type:application/json");//設置響應頭的,因為之前測試忘記了就沒有刪除,所以下面截圖里才有application/json;這里沒有必要有,只是我測試完了才看見。
echo $_POST['aa']; ?>

 

chrome截圖:    IE截圖

      你可以對照着這張截圖看你就明白了,到底這個過程是怎么樣的?其實你也不需要太了解這個過程,我們只對readyState等於4感興趣。

可以發現在chrome,firefox,opera下的測試結果是,在你實例化XMLHttpRequest對象后,這個狀態是0,當你調用了open()方法后這個狀態變為了1,這時會觸發一個readystatechange事件,你在設置頭的時候,這個狀態還是1,在你調用send()方法時,這個狀態還是1,接下來就是靠readystatechange事件來監聽了,它會被再觸發三次,當這個狀態變為2時,就接收到了響應頭信息了,當變為3的時候就接收到響應主體了,當4的時候那就響應完成了。

IE稍微有點不同就是在在設置完頭之后,還要觸發一次readystatechange事件,其他的都相同

總結readyState值

常量 含義 
UNSENT 0 open()尚未調用
OPENED 1 open()已經調用
HEADERS_RECEIVED 2 接收到頭信息
LOADING 3 接收到響應主體(內容)
DONE 4 響應完成

readystatechange事件就是在readyState屬性值每次變化的時候觸發。要是同步的就不需要監聽這個事件。

接下來就說說XMLHttpRequest對象的這四個屬性:responseText,responseXML,status,statusText,

  responseText:獲得字符串形式的響應數據(只要不是xml格式的就用這個);

  responseXML:獲得 XML 形式的響應數據;

  status:響應的Http狀態;例如200.(這個與readyState的對應關系可以看上面的截圖)

  statusText:響應的HTTP狀態說明,例如ok,其實和status是一個意思,只不過是一個用數字說明,一個用文本說明罷了,200=>ok(這個只有readyState為2,3,4時有值);

 最基礎的都介紹完了,我們再來幾個完整測試demo。

GET方式:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <!-- <meta http-equiv="X-UA-Compatible" content="IE=edge"> -->
    <title>php1</title>
    <script type="text/javascript">

window.addEventListener("load",function() {
    var btn = document.getElementById("btn");
    var content = document.getElementById("content");
    btn.addEventListener("click",function() {
        var request = new XMLHttpRequest();
        request.onreadystatechange = function() {

            if(request.readyState === 4 && request.status == 200) {
                // console.log(JSON.parse(request.responseText));
                content.innerHTML = request.responseText;
            }
        }
        request.open("GET","./test.php",true);
        // request.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");
        request.send(null);
    });
    
},false);
    </script>
</head>
<body>
<input type="button" value="點我" id="btn">
<h2>下面是點擊后的內容:</h2>
<p id="content"></p>
</body>
</html>
View Code

php:

<?php
     echo "hello!";
?>

點擊前:

點擊后

要是添加查詢參數時,只需要修改open()方法的參數;

request.open("GET","./test.php?id=3&a=5",true);

 

php

<?php
        echo "你給我的東西是:<br>";
         echo 'id是:'.$_GET['id'],"<br>";
         echo "a是:".$_GET['a'],"<br>";
         if($_GET['id']) {
             echo 'This is my respone!';
         }
?>

點擊后:

POST 方式:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <!-- <meta http-equiv="X-UA-Compatible" content="IE=edge"> -->
    <title>php1</title>
    <script type="text/javascript">

window.addEventListener("load",function() {
    var btn = document.getElementById("btn");
    var text = document.getElementById("text");
    var content = document.getElementById("content");
    btn.addEventListener("click",function() {
        var msg = "id=" + text.value;
        console.log(msg);
        var request = new XMLHttpRequest();
        request.onreadystatechange = function() {

            if(request.readyState === 4 && request.status == 200) {
                var obj = JSON.parse(request.responseText)
                if(obj['name']){
                    content.innerHTML = 'name:' + obj['name'] + '<br>' + 'age:' + obj['age'];
                } else {
                    content.innerHTML = "沒有這個人的信息";
                }
                
            }
        }
        request.open("POST","./test.php",true);
        request.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");
        request.send(msg);
    });
    
},false);
    </script>
</head>
<body>
<label>請輸入身份id:<input type="text" id="text"></label>
<input type="button" value="發送" id="btn">
<h2>下面是點擊后的內容:</h2>
<p id="content"></p>
</body>
</html>
View Code

php代碼:

<?php
        header("Content-Type:application/json");
            
        if($_POST['id'] == 001) {
            echo '{"name":"wyl","age":22}';
        } else {
            echo '{}';
        }
?>

輸入:001前:

輸入001,點擊后:

輸入其他字符點擊后:

返回JSON格式的數據記得要用JSON.parse()解析;

POST的send()也可以不傳遞數據。

還有其他類型數據格式的請求或者響應的,以后有時間再介紹。

到此處最基本的東西應該就這些了。

00x2:XMLHttpRequest level 2:

  在HTML5來臨的時候,w3c開始將這個XMLHttpRequest對象納入標准中,因為以前就存在了這個對象,現在只是更新了,所以就叫2級XMLHttpRequest;

出現新的版本一定是老的版本有不足:

有以下幾點不足:

1.以前只能傳輸文本數據,不能用來讀取和上傳二進制文件(比如圖片);

2.接收和傳遞數據時,沒有進度信息,只能知道是否傳遞完成;

3.不能進行跨域請求

新版本(XMLHttpRequest 2)的新特性:

1.可以設置HTTP的請求時限;

2.可以使用FormDate對象管理表單數據

3.可以上傳文件

4.可以進行跨資源共享(跨域)CORS;

5.有更豐富的進度事件的API

要是介紹完,篇幅太長了,我自己都不看完,都看煩了,有空着再介紹;

 

 

參考資料:

犀牛書;紅寶書;

http://www.cnblogs.com/skylar/p/ajaxCORS.html

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest

http://www.w3school.com.cn/ajax/ajax_intro.asp

http://javascript.ruanyifeng.com/bom/ajax.html

 

以上是自己結合了很多博客還有書籍總結的,僅代表個人對知識的理解和看法!如有不對的或者不准的地方,歡迎評論指正!

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM