1.
今天的內容其實挺多的,我們慢慢來說,首先第一個是xhr的基本使用,什么是xhr?
XMLHTTPRequest是瀏覽器提供的js物件,可以請求服務器上的資料資源,包括我們前面一直用的jq里面的三個請求資源的方法都是基于xhr來封裝的,
那么首先我們看到xhr的get請求怎么來實作
首先要創建xhr實體通過new來實作
然后呼叫open函式,里面值為請求方式以及url
第三步呼叫send函式
第四步監聽onreadyStateChange事件在這個事件里面要注意一下請求狀態和服務器回應狀態的固定寫法,還有服務器回應回的資料
<!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> </head> <body> <script> // 1.創建xhr物件 var xhr = new XMLHttpRequest() // 2.呼叫open函式 決定請求方式和url xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks') // 3.呼叫send函式 xhr.send() // 4.監聽事件 xhr.onreadystatechange = function() { // 4.1注意請求狀態和服務器回應狀態固定寫法 if (xhr.readyState ==4 && xhr.status == 200) { // 4.2獲取相應的資料 console.log(xhr.response); } } </script> </body> </html>0.2 1
我們看到在監聽請求狀態變化事件里有一個readystate的屬性這個屬性表示ajax當前請求所處的狀態,其中0表示xhr物件以創建,但請求未呼叫open,1表示已呼叫open函式,2表示已呼叫send函式,3表示資料接收中,最后4表示一切請求完成
那么xhr帶參的get請求怎么來實作的呢?只需要在open函式的url里面接一個查詢字串即可
xhr.open('get', 'http://www.ssfddaf.com/api?name=%df%fd%gf')
那么什么是查詢字串?
在url末尾加上?引數=值多個引數間用&來連接這就是查詢字串,無論是jQuery的三個請求方式還是xhr指定的引數其本質都是在url后帶查詢字串
這里還要了解一個點url編碼與解碼
url中只允許出線英文不允許中文等其他語種,所以他就會把除英文外其他語種轉換為%開頭帶兩個字符的樣式來代替
編碼encodeURI('中文;) 解碼decodeURI(%的字符)三組%表示一個中文
2.
接下來我們看到xhr怎么發起post請求
第一步創建物件
第二部open函式把請求方式改為post
第三步設定content-type 這是一個固定寫法
xhr.setRequestHeader(‘content-type’, ‘application/x-www-form-urlencoded’)
第四步呼叫send函式 post的引數在這里添加以查詢字串的方式添加進來
第五步監聽事件
<!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> </head> <body> <script> // 1.創建xhr物件 var xhr = new XMLHttpRequest() // 2.呼叫open函式 xhr.open('post', 'http://www.liulongbin.top:3006/api/addbook') // 3.設定cententtype xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded') // 4.呼叫send函式 xhr.send('bookname=水府傳&author=我') // 5.監聽事件 xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText); } } </script> </body> </html>
3.
資料交換格式
即服務器與客戶端之間進行資料傳輸與交換的格式,XML和JSON這兩種
XML我們用的比較少,它是可擴展標記語言,跟html很相似
JSON
什么事json,就是js物件和陣列的字串表示法,其中本質還是一個字串它是輕量級文本資料交換格式
它的結構為有兩種物件結構和陣列結構
物件結構
‘{key:value}’咋一看跟物件很相似,但是首先外面會有引號,其次鍵值是字符型別必須加雙引號
陣列結構
【a,a】
要注意的是鍵值的雙引號,json中不能寫注釋,不能使用undefined和函式作為值
json和物件互轉
obj = JSON.parse(json)(反序列化)
json = JSON.stringify(obj)(序列化)
4.
封裝自己的ajax函式
①先封裝一個處理data物件為查詢字串的函式
②封裝函式xhr
③判斷不同的請求型別達到不同的方式
這個總之記住一點就是xhr呼叫請求的總體步驟就沒得問題
// 1.先封裝函式處理傳進來的引數為查詢字串 function revolveData(data) { var arr = [] for (var k in data) { arr[arr.length] = k + '=' + data[k] } var str = arr.join('&') return str } // console.log(revolveData({name : '張三', age : 19})); // 2,封裝主體函式 function ajaxMine(obj) { var xhr = new XMLHttpRequest() var str = revolveData(obj.data) xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { var res = JSON.parse(xhr.response) obj.success(res) } } // 3.判斷不同的請求,做到不同的操作 if (obj.method.toUpperCase() == 'GET') { xhr.open(obj.method, obj.url + '?' +str) xhr.send() } else if (obj.method.toUpperCase() == 'POST') { xhr.open(obj.method, obj.url) xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded') xhr.send(str) } }
驗證
<!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> </head> <body> <script src="./封裝自己的ajax函式.js"></script> <script> /* ajaxMine({ method : 'get', url : 'http://www.liulongbin.top:3006/api/getbooks', data : { id : 2 }, success : function(res) { console.log(res); } }) */ ajaxMine({ method : 'post', url : 'http://www.liulongbin.top:3006/api/addbook', data : { bookname : '收首飾', author : '東風似舊', publisher : '身法' }, success : function(res) { console.log(res); } }) </script> </body> </html>
5.
xhr level2新特性
在我們舊版的xhr缺點就是不支持檔案上傳而且沒有進度資訊只有完沒完成
在我們新版xhr
支持檔案上傳,有進度資訊,還可以設定http時限,還可使用formdata物件管理表單資料
接下來我會一一開始xhr這四個新特性
5.1
首先第一個設定Http時限,也就是在規定時間如果還沒有完成請求任務那么這個請求就失敗了
xhr.timeout = 2000
與之對應的還有一個ontimeout的事件在超時后會做些什么
<!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> </head> <body> <script> var xhr = new XMLHttpRequest() xhr.timeout = 50 xhr.ontimeout = function() { console.log('請求超時了'); } 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); } } </script> </body> </html>
5..2
formdata管理表單
因為我們ajax主要是用來提交表單資料的嘛,所以H5就新增了一個FormData物件用來模擬表單操作
①新建formdata物件
②為formdata添加表單項
③創建xhr
④用xhr完成請求
<!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> </head> <body> <script> // 1.創建FormData物件 var fd = new FormData() // 2.往里面添加表單項 fd.append('uname', '王五') fd.append('age' , 29) // 3,創建xhr物件 var xhr = new XMLHttpRequest() // 4.使用xhr物件制定請求型別與地址 xhr.open('post', 'http://www.liulongbin.top:3006/api/formdata') // 5.直接提交,formdata物件,這與提交網頁表單的效果完全一樣 xhr.send(fd) // 6.驗證 xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responsete); } } </script> </body> </html>
formdata還有一個用法,就是可以用來獲取表單的值
<!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> </head> <body> <form action=""> <input type="text" name="uname"> <input type="password" name="pwd"> <input type="submit" value="提交"> </form> <script> var form = document.querySelector('form') form.onsubmit = e => { e.preventDefault() var xhr = new XMLHttpRequest() var fd = new FormData(form) xhr.open('post', 'http://www.liulongbin.top:3006/api/formdata') xhr.send(fd) xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText); } } } </script> </body> </html>
5.3
上傳檔案
①定義UI結構
②驗證是否選擇了檔案
③像formdata追加檔案
④用xhr發起上傳請求
⑤監聽事件
<!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> </head> <body> <!-- 1.定義ui結構 --> <!-- 1.1檔案選擇框 --> <input type="file"> <!-- 1.2上傳按鈕 --> <input type="submit" value="上傳檔案"> <!-- 1.3img標簽 用來顯示上傳成功后的圖片 --> <img src="" alt=""> <script> // 2.驗證是否上傳了檔案 var uploadBtn = document.querySelector('input:nth-of-type(2)') uploadBtn.addEventListener('click', function() { // 2.1注意這里這個,files它是一個陣列存放的是檔案 let files = document.querySelector('input:first-child').files if (files.length > 0) { // 3.像formdata中追加檔案 var fd = new FormData() // avator為頭像假裝這里是上傳的頭像 fd.append('avatar', files[0]) // 4.使用xhr發起上傳檔案請求 var xhr = new XMLHttpRequest() xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar') xhr.send(fd) // 5.監聽事件 xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { // console.log(xhr.responseText); let imgData = JSON.parse(xhr.responseText) if (imgData.status == 200) { document.querySelector('img').src = 'http://www.liulongbin.top:3006' + imgData.url } else { console.log('上傳檔案失敗'); } } } } else { return alert('請上傳檔案') } }) </script> </body> </html>
5.4
顯示上傳進度

通過xhr.upload.onprogress事件來監聽這里面有三個屬性值得注意一下
<!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> </head> <body> <!-- 1.定義ui結構 --> <!-- 1.1檔案選擇框 --> <input type="file"> <!-- 1.2上傳按鈕 --> <input type="submit" value="上傳檔案"> <!-- 1.3img標簽 用來顯示上傳成功后的圖片 --> <img src="" alt=""> <script> // 2.驗證是否上傳了檔案 var uploadBtn = document.querySelector('input:nth-of-type(2)') uploadBtn.addEventListener('click', function() { // 2.1注意這里這個,files它是一個陣列存放的是檔案 let files = document.querySelector('input:first-child').files if (files.length > 0) { // 3.像formdata中追加檔案 var fd = new FormData() // avator為頭像假裝這里是上傳的頭像 fd.append('avatar', files[0]) // 4.使用xhr發起上傳檔案請求 var xhr = new XMLHttpRequest() // -------------------------------- // 1.上傳進度監聽事件 xhr.upload.onprogress = e => { // 2.引數一 e.lengthComputable是一個布林值,表示當前上傳的資源是否具有可計算的長度要有才能進去 if (e.lengthComputable) { // 引數二e.loaded已傳輸的位元組 // 引數三e.total需傳輸的總位元組 var percenComplete = Math.ceil((e.loaded / e.total) * 100) console.log(percenComplete); } } xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar') xhr.send(fd) // 5.監聽事件 xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { // console.log(xhr.responseText); let imgData = JSON.parse(xhr.responseText) if (imgData.status == 200) { document.querySelector('img').src = 'http://www.liulongbin.top:3006' + imgData.url } else { console.log('上傳檔案失敗'); } } } } else { return alert('請上傳檔案') } }) </script> </body> </html>
知道了上傳進度我們就可以通過bootstrap來一個進度條板的上傳進度
<!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> <link rel="stylesheet" href="../day01/lib/bootstrap.css"> </head> <body> <!-- 1.定義ui結構 --> <!-- 1.1檔案選擇框 --> <input type="file"> <!-- 1.2上傳按鈕 --> <input type="submit" value="上傳檔案"> <!-- 1.3img標簽 用來顯示上傳成功后的圖片 --> <img src="" alt=""> <!-- 進度條 --> <div class="progress" style="width: 500px;"> <div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"> 0% </div> </div> <script> // 2.驗證是否上傳了檔案 var uploadBtn = document.querySelector('input:nth-of-type(2)') uploadBtn.addEventListener('click', function() { // 2.1注意這里這個,files它是一個陣列存放的是檔案 let files = document.querySelector('input:first-child').files if (files.length > 0) { // 3.像formdata中追加檔案 var fd = new FormData() // avator為頭像假裝這里是上傳的頭像 fd.append('avatar', files[0]) // 4.使用xhr發起上傳檔案請求 var xhr = new XMLHttpRequest() // -------------------------------- // 1.監聽事件 var program = document.querySelector('.progress-bar') xhr.upload.onprogress = e => { // 2.引數一 e.lengthComputable是一個布林值,表示當前上傳的資源是否具有可計算的長度要有才能進去 if (e.lengthComputable) { // 引數二e.loaded已傳輸的位元組 // 引數三e.total需傳輸的總位元組 var percenComplete = Math.ceil((e.loaded / e.total) * 100) // console.log(percenComplete); program.style.width = percenComplete + '%' program.innerText = '%' + percenComplete } } xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar') xhr.send(fd) // 5.監聽事件 xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { // console.log(xhr.responseText); let imgData = JSON.parse(xhr.responseText) if (imgData.status == 200) { document.querySelector('img').src = 'http://www.liulongbin.top:3006' + imgData.url } else { console.log('上傳檔案失敗'); } } } } else { return alert('請上傳檔案') } }) </script> </body> </html>
最后完善上傳成功的進度條
<!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> <link rel="stylesheet" href="../day01/lib/bootstrap.css"> </head> <body> <!-- 1.定義ui結構 --> <!-- 1.1檔案選擇框 --> <input type="file"> <!-- 1.2上傳按鈕 --> <input type="submit" value="上傳檔案"> <!-- 1.3img標簽 用來顯示上傳成功后的圖片 --> <img src="" alt=""> <!-- 進度條 --> <div class="progress" style="width: 500px;"> <div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"> 0% </div> </div> <script> // 2.驗證是否上傳了檔案 var uploadBtn = document.querySelector('input:nth-of-type(2)') uploadBtn.addEventListener('click', function() { // 2.1注意這里這個,files它是一個陣列存放的是檔案 let files = document.querySelector('input:first-child').files if (files.length > 0) { // 3.像formdata中追加檔案 var fd = new FormData() // avator為頭像假裝這里是上傳的頭像 fd.append('avatar', files[0]) // 4.使用xhr發起上傳檔案請求 var xhr = new XMLHttpRequest() // -------------------------------- // 1.監聽事件 var program = document.querySelector('.progress-bar') xhr.upload.onprogress = e => { // 2.引數一 e.lengthComputable是一個布林值,表示當前上傳的資源是否具有可計算的長度要有才能進去 if (e.lengthComputable) { // 引數二e.loaded已傳輸的位元組 // 引數三e.total需傳輸的總位元組 var percenComplete = Math.ceil((e.loaded / e.total) * 100) // console.log(percenComplete); program.style.width = percenComplete + '%' program.innerText = '%' + percenComplete } } // ----------------------------------- // 2.上傳成功進度條變化 xhr.upload.onload = () => { program.className = '' program.className = 'progress-bar progress-bar-success' } xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar') xhr.send(fd) // 5.監聽事件 xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { // console.log(xhr.responseText); let imgData = JSON.parse(xhr.responseText) if (imgData.status == 200) { document.querySelector('img').src = 'http://www.liulongbin.top:3006' + imgData.url } else { console.log('上傳檔案失敗'); } } } } else { return alert('請上傳檔案') } }) </script> </body> </html>
6.
jQuery高級用法
用jq來實作檔案上傳
①定義ui結構和前面一樣
②驗證是否選擇檔案
③向formdata追加檔案
④使用jq發起上傳請求
⑤jq實作loading效果 兩個方法一檢測到任何ajax開始或失敗就會呼叫
<!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> </head> <body> <!-- 1.定義UI結構 --> <form action=""> <input type="file" name="file" id=""> </form> <!-- 這里出現了一點小問題 我在后面列印res始終列印不出來而且反正就想資料被清了一下思來想去才知道是我把button放在表單里了所以一點擊就會造成默認行為 --> <button type="submit">上傳圖片</button> <img style="display: none;" src="../../../../HTML/04-階段四 前后端互動/第四階段:前后端互動階段資料新/ajax課程資料/day3(7-12小節)/code/images/loading.gif" alt=""> <script src="../day01/lib/jquery.js"></script> <script> // 5.這個方法是偵聽到所有的ajax請求就會開始執行 $(document).ajaxStart(function() { $('img').show() }) $(document).ajaxStop(function() { $('img').hide() }) // 2.驗證是否選擇了檔案 $('button').on('click', function() { // 這里需要將jq物件轉為原生dom物件來使用files這個屬性 var files = $('input')[0].files // console.log(files); if (files.length <= 0) { return alert('請選擇檔案') } else { // 3.向formdata追加檔案 var fd = new FormData() fd.append('avatar', files[0]) // 4.利用jq來發起上傳請求 $.ajax({ method: 'POST', url: 'http://www.liulongbin.top:3006/api/upload/avatar', data: fd, processData: false, contentType: false, success: function (res) { console.log(res) } }) } }) </script> </body> </html>
7.
axios
今天的最后一個內容,什么事axios,專注于網路資料請求的庫,相比于原生xhr更簡單易用,相比于jq更輕量化
<!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="./axios.js"></script> </head> <body> <button>發起get請求</button> <script> var btn = document.querySelector('button') /* btn.onclick = function() { var url = 'http://www.liulongbin.top:3006/api/get' var obj = {name : '張三', age : 29} axios.get(url, {params: obj}).then(function(res) { console.log(res); }) } */ btn.onclick = () => { axios({ method : 'get', url : 'http://www.liulongbin.top:3006/api/get', params : {name : '張三', age : 29} }).then(res => console.log(res)) } </script> </body> </html>
<!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="./axios.js"></script> </head> <body> <button>發起post請求</button> <script> /* document.querySelector('button').onclick =function() { var url = 'http://www.liulongbin.top:3006/api/post' var obj = {location : '重慶', address : '江北'} axios.post(url, {obj}).then(res => console.log(res)) } */ document.querySelector('button').onclick = () => { axios({ method : 'post', url : 'http://www.liulongbin.top:3006/api/post', data : {name : '張三', age : 29} }).then(res => console.log(res)) } </script> </body> </html>
<!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> <link rel="stylesheet" href="../day01/lib/bootstrap.css"> </head> <body> <!-- 1.定義ui結構 --> <!-- 1.1檔案選擇框 --> <input type="file"> <!-- 1.2上傳按鈕 --> <input type="submit" value="上傳檔案"> <!-- 1.3img標簽 用來顯示上傳成功后的圖片 --> <img src="" alt="">
<!-- 進度條 --> <div class="progress" style="width: 500px;"> <div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"> 0% </div> </div> <script> // 2.驗證是否上傳了檔案 var uploadBtn = document.querySelector('input:nth-of-type(2)') uploadBtn.addEventListener('click', function() { // 2.1注意這里這個,files它是一個陣列存放的是檔案 let files = document.querySelector('input:first-child').files if (files.length > 0) { // 3.像formdata中追加檔案 var fd = new FormData() // avator為頭像假裝這里是上傳的頭像 fd.append('avatar', files[0])
// 4.使用xhr發起上傳檔案請求 var xhr = new XMLHttpRequest() // -------------------------------- // 1.監聽事件 var program = document.querySelector('.progress-bar') xhr.upload.onprogress = e => { // 2.引數一 e.lengthComputable是一個布林值,表示當前上傳的資源是否具有可計算的長度要有才能進去 if (e.lengthComputable) { // 引數二e.loaded已傳輸的位元組 // 引數三e.total需傳輸的總位元組 var percenComplete = Math.ceil((e.loaded / e.total) * 100) // console.log(percenComplete); program.style.width = percenComplete + '%' program.innerText = '%' + percenComplete } } // ----------------------------------- // 2.上傳成功進度條變化 xhr.upload.onload = () => { program.className = '' program.className = 'progress-bar progress-bar-success' } xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar') xhr.send(fd) // 5.監聽事件 xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { // console.log(xhr.responseText); let imgData = JSON.parse(xhr.responseText) if (imgData.status == 200) { document.querySelector('img').src = 'http://www.liulongbin.top:3006' + imgData.url } else { console.log('上傳檔案失敗'); } } } } else { return alert('請上傳檔案') } }) </script> </body> </html>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/457609.html
標籤:JavaScript
