首頁 > 軟體

原生Ajax之全面瞭解xhr的概念與使用

2022-11-21 14:02:12

XHR的基本使用  

什麼是XHR

xhr是瀏覽器提供的JavaScript物件,通過它,可以請求伺服器上的資料資源,之前所學的jquery的ajax函數,就是基於xhr物件封裝出來的。

使用xhr發起GET請求

步驟
1.建立xhr物件
2.使用xhr.open()函數
3.呼叫xhr.send()函數
4.監聽xhr.onreadystatechange事件。

        //建立xhr物件
        let xhr = new XMLHttpRequest();
        //呼叫open函數
        xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks')
        //呼叫send函數
        xhr.send()
        //監聽事件
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                //獲取成功
                console.log(xhr.responseText);
            }
        }

瞭解xhr物件的readyState屬性

XHR物件的readyState屬性,用來表示當前Ajax請求所處的狀態,每個Ajax請求必然處於一下狀態中的一個:

狀態描述
0UNSENTXMLHttpRequest物件已被建立,但尚未呼叫open方法。
1OPENEDopen()方法已經被呼叫
2HEADERS_RECEIVEDsend()方法已經被呼叫,響應頭也已經接受
3LOADING資料接受中,此時response屬性中已經包含部分資料
4DONEAjax請求完成,這意味著資料傳輸已經徹底完成或失敗

使用xhr發起帶引數的GET請求

使用xhr物件發起帶引數的get請求時,只需在呼叫xhr.open期間,為URL地址指定引數即可,在地址後面寫上?後面以鍵值對的形式寫上資料,多個資料用&連線。

        //建立xhr物件
        let xhr = new XMLHttpRequest();
        //呼叫open函數
        xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks?id=1')
        //呼叫send函數
        xhr.send()
        //監聽事件
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                //獲取成功
                console.log(xhr.responseText);
            }
        }

URL編碼與解碼    

什麼是URL編碼

URL地址中,只允許出現英文相關的字母,標點符號,數位,因此。在URL地址中不允許出現中文字元。
如果URL中需要包含中文這樣的字元,則必須對中文字元進行編碼(跳脫)。
URL編碼的原則,使用安全的字元,(沒有特殊用途或者特殊意義的可列印字元)去表示那些不安全的字元。

如何對URL進行編碼與解碼

瀏覽器提供了URL編碼與解碼的API,分別是:

  • encodeURI() 編碼的函數
  • decodeURI()解碼的函數
        let str = '黑馬程式設計師';
        let str2 = encodeURI(str)
        console.log(str2);
        //utf-8一個漢字佔三個位元組 ,寫六個是黑馬兩個字。
        let str3 = decodeURI('%E9%BB%91%E9%A9%AC')
        let str4 = decodeURI(str2)
        console.log(str3);
        console.log(str4);

使用xhr發起post請求

步驟
1.建立xhr物件
2.呼叫xhr.open()函數
3.設定Content-Type屬性(固定寫法)
4.呼叫xhr.send()函數。同時指定要傳送的資料。
5.監聽xhr.onreadystatechange事件

        //建立xhr物件
        let xhr = new XMLHttpRequest();
        //呼叫open()
        xhr.open('post', 'http://www.liulongbin.top:3006/api/addbook');
        //設定Content-Type(固定寫法)
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

        //呼叫send函數
        xhr.send('bookname=水滸傳&author=施耐庵&publisher=上海圖書出版社')
        //監聽事件
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                console.log(xhr.responseText);
            }
        }

資料交換格式  

什麼是資料交換格式

資料交換格式,就是伺服器端與使用者端之間進行資料傳輸與交換的格式.

前端領域,經常提及的兩種資料交換格式分別是XML和JSON。其中XML用的非常少,所以,我們重點要學習的資料交換格式JSON。

XML    

什麼是XML

xml的英文全稱是EXtensible Markup Language,即可延伸標示語言,因此,XML和HTML類似,也是一種標示語言。

XML和HTML的區別

xml和html雖然都是標示語言,但是,他們兩者之間沒有任何的關係。

  • HTML被設計用來描述網頁上的內容,是網頁內容的載體
  • XML被設計用來傳輸和儲存資料,是資料的載體

XML的缺點

1.XML格式臃腫,和資料無關的程式碼多,體積大,傳輸效率低。

2.在JavaScript中解析XML比較麻煩。

JSON    

什麼是JSON

概念:JSON的英文全稱是JavaScript Object Notation,即 JavaScript物件表示法。簡單來講,JSON就是JavaScript物件和陣列的字串表示法,它使用文字表示一個JS物件或陣列的資訊,因此,JSON的本質是字串。

作用:JSON是一種輕量級的文字資料交換格式,在作用上類似XML,專門用於儲存和傳輸資料,單是JSON比XML更小,更快,更易解析。

現狀:JSON是在2001年開始被推廣和使用的資料格式,到現今為止,JSON已經成為了主流的資料交換格式。

JSON的兩種結構

JSON就是用字串來表示JavaScript的物件和陣列兩種結構,通過這兩種結構的相互巢狀,可以表示各種複雜的資料結構。

  • 物件結構:物件結構在JSON中表示為{}括起來的內容,資料結構為{key:value,key:value,…}的鍵值對結構,其中,key必須是使用英文的雙引號包裹的字串,value的資料型別可以是數位,字串,布林值,null,陣列,物件六種型別。
  • 陣列結構:陣列結構在JSON中表示為[]括起來的內容,資料結構為[‘java’,‘javascript’,30,true],陣列中資料的型別可以是數位,字串,布林值,null,陣列,物件6種型別。

JSON語法的注意事項

1.屬性名必須使用雙引號包裹。

2.字串型別的值必須使用雙引號包裹

3.JSON中不允許使用單引號表示字串

4.JSON中不能寫註釋

5.JSON的最外層必須是物件或陣列格式。

6.不能使用undefined或函數作為JSON的值

JSON的作用:在計算機與網路之間儲存和傳輸資料。

JSON的本質:用字串來表示JavaScript物件資料或陣列資料。

JSON和JS物件的關係

JSON是js物件的字串表示法,它使用文字表示一個js物件的資訊,本質是一個字串。例如:

var jsobj ={a:'hello',b:'world'}
var jsonstr = '{'a':'hello','b':'world'}'

JSON和JS物件的互轉

要實現從JSON字串轉換為js物件,使用JSON.parse()方法;

        var xhr = new XMLHttpRequest();
        xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks');
        xhr.send();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                console.log(xhr.responseText);
                var restr = JSON.parse(xhr.responseText)
                console.log(restr);
            }
        }

要實現從JS物件轉換為JSON字串,使用JSON.stringify()方法:

序列化和反序列化

把資料物件轉換為字串的過程,叫做序列化,例如:呼叫JSON.stringify()函數的操作,叫做JSON序列化。

把字串轉換為資料物件的過程,叫做反序列化,例如:呼叫JSON.parse()函數的操作,叫做JSON的反序列化。

封裝自己的Ajax函數  

要實現的效果

定義一個名為itheima的ajax函數,匯入js檔案之後,可以進行呼叫檔案內的相關函數。

定義options引數選項

itheima()函數是我們自定義的Ajax函數,它接受一個設定物件作為引數,設定物件中可以設定如下屬性:

  • method 請求的型別
  • url 請求的URL地址
  • data 請求攜帶的資料
  • success 請求成功之後的回撥函數

處理data引數

需要把data物件,轉化成查詢字串的格式,從而提交給伺服器,因此提前定義resolveData函數如下:

function resolveData(data) {
    var arr = [];
    for (const k in data) {
        //這裡說一下物件的呼叫方法,物件呼叫可以使用【】和點,這裡的物件呼叫需要用【】的,k是字串,點後面不能是字串,所以不能直接data.k,
        //我們可以先進行字串連結data.k再使用eval方法進行解析,就可以使用點呼叫了
        // var str = k + '=' + eval("data." + k);
        var str = k + '=' + data[k];
        arr.push(str);
    }
    return arr.join('&')
}
var str = resolveData({ name: 'xiaoxie', age: 20 });
console.log(str);

定義itheima函數

在itheima()函數中,需要建立xhr物件,並監聽onreadystatechange事件。

function itheima(options) {
    let xhr = new XMLHttpRequest();
    let qs = resolveData(options.data)
--------判斷型別 發起請求 程式碼--------------
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
         let result = JSON.parse(xhr.responseText)
            options.success(result)

        }
    }
}

判斷請求的型別

不同的請求型別,對應的xhr物件的不同操作,因此需要對請求型別進行if…else…的判斷。

    if (options.method.toUpperCase() === 'GET') {
       xhr.open('get', options.URL + '?' + qs)
        xhr.send();
   } else if (options.method.toUpperCase() === 'POST') {
       xhr.open('post', options.URL)
       xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
       xhr.send(qs);
   }

xhr level2的新特性  

舊版xhr的缺點

  1. 只支援文字資料的傳輸,無法用來讀取和上傳檔案。
  2. 傳送和接受資料時,沒有進度資訊,只能提示有沒有完成。

xhr levle2的新特性

  • 可以設定http請求的時限。
  • 可以使用formdata物件管理表單資料
  • 可以上傳檔案
  • 可以獲得資料傳輸的進度資訊。

設定http請求時限。

有時,Ajax操作很耗時,而且無法預知要花多少時間。如果網速很慢,使用者可能要等很久,新版本的xhr物件,增加了timeout屬性,可以設定http請求的時限:

xhr.timeout = 3000

上面的語句,將最長等待時間設為3000毫秒,過了這個時限,就自動停止http請求。與之配套的還有一個timeout事件,用來指定回撥函數。

xhr.ontimeout = function(event){
alert('請求超時')
}
        let xhr = new XMLHttpRequest();
       xhr.timeout = 30;
       xhr.ontimeout = function () {
           console.log(請求超時);
       }
       xhr.open('get', 'http://liulongbin.top:3006/api/getbooks')
       xhr.send()
       xhr.onreadystatechange = function () {
           if (xhr.readyState === 4 && xhr.status == 200) {
               console.log(xhr.responseText);
           }

       }

FormData物件管理表單資料

Ajax操作往往用來提交表單資料。為了方便表單處理,HTML5新增了一個FormData物件,可以模擬表單操作。

        let fd = new FormData();
        fd.append('uname', 'xiaoxie')
        fd.append('pwd', 123456)
        let xhr = new XMLHttpRequest();
        xhr.open('post', 'http://www.liulongbin.top:3006/api/formdata')
        xhr.send(fd);
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status == 200) {
                console.log(JSON.parse(xhr.responseText));
            }
        }

FormData物件也可以用來獲取網頁表單的值,不用通過serialize()方法轉換,可以獲取值後可以直接使用,不用通過範例程式碼如下:

        var form = document.querySelector('#form1')
        form.addEventListener('submit', function (e) {
            e.preventDefault();

            //建立物件,獲取資料。
            let fd = new FormData(form);

            let xhr = new XMLHttpRequest();

            xhr.open('post', 'http://www.liulongbin.top:3006/api/formdata')

            xhr.send(fd)
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    console.log(JSON.parse(xhr.responseText));
                }
            }
        })

上傳檔案

新版xhr物件,不僅可以傳送文字資訊,還可以上傳檔案。

  • 定義ui結構
  • 驗證是否選擇了檔案
  • 向FormData中追加檔案
  • 使用xhr發起上傳檔案的請求
  • 監聽onreadystatechange事件

定義UI結構

    <!-- 檔案選擇框 -->
    <input type="file" id="file1">
    <!-- 上傳檔案的按鈕 -->
    <button id="btnUpload"></button>
    <br>
    <img src="" alt="" id="img" width="800">

驗證是否選擇了檔案

        //獲取檔案上傳按鈕
        let btn = document.getElementsByTagName('button')[0];
        //為按鈕繫結單擊事件處理常式
        btn.addEventListener('click', function () {
            //獲取使用者選擇的檔案滑鼠
            let files = document.querySelector('#file1').files;

            if (files.length <= 0) {
                return alert('請選擇要上傳的檔案')
            }
            console.log('使用者選擇了待上傳的檔案');
        })

向FormData中追加檔案

 let fd = new FormData()
  fd.append('avatar', files[0])

使用xhr發起上傳檔案的請求

           let xhr = new XMLHttpRequest();
            xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar')
            xhr.send(fd)

監聽onreadystatechange事件

            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    let data = JSON.parse(xhr.responseText)
                    if (data.status === 200) {
                        //上傳成功
                        alert('上傳成功')
                        document.getElementById('img').src = 'http://www.liulongbin.top:3006' + data.url
                    } else {
                        console.log('圖片上傳失敗' + data.message);
                    }
                }
            }

顯示檔案上傳進度

新版本的XHR物件中,可以通過監聽xhr.upload.onprogress事件,來獲取到檔案的上傳進度,語法格式如下:

            //監聽上傳進度
            xhr.upload.onprogress = function (e) {
                if (e.lengthComputable) {
                    let uploadProgroess = Math.ceil((e.loaded / e.total) * 100)
                    console.log(uploadProgroess);
                }
            }

美化進度顯示

 <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
        integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
 //設定進度條
$('#percent').attr('style', 'width:' + uploadProgroess).html(uploadProgroess + '%')

完整程式碼

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
        integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>

<body>
    <!-- 檔案選擇框 -->
    <input type="file" id="file1">
    <!-- 上傳檔案的按鈕 -->
    <button id="btnUpload">上傳檔案</button>
    <br>
    <img src="" alt="" id="img" width="800">
    <div class="progress" style="width: 300px;">
        <div class="progress-bar progress-bar-striped active" style="width: 0%" id="percent">
            0%
        </div>
    </div>
    <script>
        //獲取檔案上傳按鈕
        let btn = document.getElementsByTagName('button')[0];
        //為按鈕繫結單擊事件處理常式
        btn.addEventListener('click', function () {
            //獲取使用者選擇的檔案屬性,是一個陣列。
            let files = document.querySelector('#file1').files;
            if (files.length <= 0) {
                return alert('請選擇要上傳的檔案')
            }
            //表單中新增相應的資料
            let fd = new FormData()
            fd.append('tupian', files[0])
            //使用xhr發起上傳檔案的請求
            let xhr = new XMLHttpRequest();
            //監聽上傳進度
            xhr.upload.onprogress = function (e) {
                if (e.lengthComputable) {
                    let uploadProgroess = Math.ceil((e.loaded / e.total) * 100)
                    console.log(uploadProgroess);
                    //設定進度條
                    $('#percent').attr('style', 'width:' + uploadProgroess).html(uploadProgroess + '%')
                }
            }
            xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar')
            xhr.send(fd)
            //監聽onreadystatechange事件
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    let data = JSON.parse(xhr.responseText)
                    if (data.status === 200) {
                        //上傳成功
                        alert('上傳成功')
                        document.getElementById('img').src = 'http://www.liulongbin.top:3006' + data.url
                    } else {
                        console.log('圖片上傳失敗' + data.message);
                    }
                }
            }
        })


    </script>
</body>

</html>

總結

到此這篇關於原生Ajax之全面瞭解xhr的概念與使用的文章就介紹到這了,更多相關原生Ajax xhr概念與使用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com