Vue網(wǎng)絡(luò)請求的三種實現(xiàn)方式介紹
在進(jìn)行 Vue 的網(wǎng)絡(luò)請求之前,我們先寫一些假數(shù)據(jù):
users.json:
[ { "id": 1, "name": "張三" }, { "id": 2, "name": "李四" } ]
1.XMLHttpRequest發(fā)送請求
使用 XMLHttpRequest 請求 users.json 中的數(shù)據(jù):
<div id="app"> <ul> <li v-for="item in users" :key="item.id">{{item.name}}</li> </ul> </div> <script> const vm = new Vue({ el: '#app', data: { users: [] }, mounted() { const xhr = new XMLHttpRequest() // // true 表示發(fā)送異步請求 xhr.open('get', '/mock/users.json', true) // // 寫法1 // xhr.onreadystatechange = () => { // // 0 - 4 xhr.readyState狀態(tài)值 // if (xhr.readyState === 4 && xhr.status === 200) { // console.log(JSON.parse(xhr.responseText)); // this.users = JSON.parse(xhr.responseText) // } // } // 寫法2 xhr.onload = ()=>{ console.log(JSON.parse(xhr.responseText)); this.users = JSON.parse(xhr.responseText) } xhr.send(null) } }) </script>
注意:上面介紹了兩種方法,分別是onreadystatechange
和onload
,我們需要知道這兩種方法的區(qū)別 。XMLHttpRequest 對象有一個屬性 readyState,將其 (xhr.readyState) 打印后發(fā)現(xiàn):進(jìn)入onreadystatechange
請求方式中時,可以打印其狀態(tài)為2,狀態(tài)為3,狀態(tài)為4;進(jìn)入onload
之后,只出現(xiàn)了狀態(tài)碼4。也就是說,只有處于狀態(tài)碼4,請求已完成,響應(yīng)已就緒的情況下,才會進(jìn)入onload
。只要進(jìn)入onload
請求中,一定是已經(jīng)到4這個狀態(tài)了。nreadystatechange()的定義是只要返回的狀態(tài)碼只要變化時就回調(diào)一次函數(shù),而onload只有狀態(tài)碼為4時才能回調(diào)一次函數(shù)。
2.fetch發(fā)送請求
使用 fetch 請求 users.json 中的數(shù)據(jù):
<div id="app"> <ul> <li v-for="item in users" :key="item.id">{{item.name}}</li> </ul> </div> <script> const vm = new Vue({ el: '#app', data: { users: [] }, // 兼容寫法 mounted() { fetch('/mock/users.json') .then(ret => ret.json()) .then(json => this.users = json) } // 高版本寫法 // async mounted() { // let ret = await fetch('/mock/users.json') // this.users = await ret.json() // } // 高版本裝逼寫法 // async mounted() { // this.users = await (await fetch('/mock/users.json')).json // } }) </script>
3.axios請求庫(Vue中推薦寫法)
概述:
Axios 是一個基于 promise 的 HTTP 庫,可以用在瀏覽器和node.js中。能攔截請求和響應(yīng),自動轉(zhuǎn)換JSON數(shù)據(jù)。axios也是vue作者推薦使用的網(wǎng)絡(luò)請求庫。
優(yōu)勢:
- 使用人群多
- 對 Ts 支持非常好
- 跨平臺(nodejs、移動端)
- 基于 promise ,異步變同步,寫法簡單
- 添加了攔截器等封裝好的函數(shù),使用更加方便
使用方法:
<div id="app"> <ul> <li v-for="item in users" :key="item.id">{{item.name}}</li> </ul> </div> <script src="./js/axios.js"></script> <script> const vm = new Vue({ el: '#app', data: { users: [] }, mounted() { // 獲取數(shù)據(jù)的簡單使用 axios.get('/mock/users.json').then(ret => { console.log(ret.data); this.users=ret.data; }) } }) </script>
模擬發(fā)送get和post請求
創(chuàng)建自己的服務(wù)器,模擬發(fā)送 get 和 post 請求
步驟1:
使用npm init -y
初始化 node.js 配置文件
步驟2:
使用npm i -S express
,安裝 express
步驟3:
新建app.js
,并且修改package.json
文件如下
準(zhǔn)備工作完成后,我們就可以書寫服務(wù)端代碼了:
app.js:
const express = require('express') const app = express() app.listen(9000, () => { console.log('http://localhost:9000') }) // 中間件 // 解決跨域 npm i -S cors 下載并寫入配置文件 app.use(require('cors')()) // post提供,內(nèi)容為json格式 app.use(express.json()) app.get('/api/users', (req, res) => { // 解決跨域問題 // res.setHeader('Access-Control-Allow-Origin', '*') res.send({ code: 0, msg: 'ok', data: { users: [ { id: 1, name: '張三' }, { id: 2, name: '李四' } ], // 獲取用戶認(rèn)證信息 token: req.headers?.token } }) }) app.post('/api/users', (req, res) => { res.send({ code: 0, msg: 'ok', // 把傳過來的參數(shù)再返回出去 data: req.body }) }) // patch/put // patch 增量更新 // put 全量更新 app.put('/api/users/:id', (req, res) => { res.send({ code: 0, msg: 'ok', data: req.body }) }) app.delete('/api/users/:id', (req, res) => { // 返回 204 意味著不會返回任何數(shù)據(jù) // res.status(204).send({ res.status(200).send({ code: 0, msg: 'ok', data: { id: req.params.id } }) })
前端獲取數(shù)據(jù):
<!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>vue學(xué)習(xí)使用</title> <!-- 第1步: 引入vue庫文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:掛載點(diǎn) --> <div id="app"> <ul> <li v-for="item in users" :key="item.id">{{item.name}}</li> </ul> </div> <!-- 第3步:實例化vue --> <script src="./js/axios.js"></script> <script> // axios全局配置 這里的地址會自動補(bǔ)全到 get 或 post 要請求的地址中 // 可以寫在配置文件中,方便修改 axios.defaults.baseURL = 'http://localhost:9000'; // 全局設(shè)置網(wǎng)絡(luò)請求超時時間,10s中還沒請求到數(shù)據(jù),就停止請求 axios.defaults.timeout = 10000 const vm = new Vue({ el: '#app', data: { users: [] }, mounted() { // 發(fā)送 get 請求 // axios.get('/api/users').then(ret => { // console.log(ret.data); // // 只會監(jiān)聽當(dāng)前 then 方法中是否有異常 // }, () => console.log('有異常')) // 發(fā)送 post 請求 // axios.post('/api/users', { // name: '李四' // }).then(ret => { // console.log(ret.data); // }) // 發(fā)送 put 請求 // axios.put('/api/users', { // name: '李四 -- put' // }).then(ret => { // console.log(ret.data); // }) // 發(fā)送 delete 請求 axios.delete('/api/users/100').then(ret => { console.log(ret.data); }) } }) </script> </body> </html>
注意:
超時請求不到數(shù)據(jù)就報出異常,這種捕獲異常的方式,會監(jiān)聽前面所有的 then 方法
axios.get('/api/users').then(ret => { console.log(ret.data); }).catch(() => console.log('有異常'))
下面這種寫法,只會監(jiān)聽當(dāng)前 then 方法中是否有異常:
axios.get('/api/users').then(ret => { console.log(ret.data); },() => console.log('有異常'))
網(wǎng)絡(luò)請求時發(fā)送用戶認(rèn)證信息
有時候我們通過網(wǎng)絡(luò)請求一個服務(wù)器的時候,需要攜帶一個用戶認(rèn)證信息,例如用戶只有在登錄狀態(tài)下才能獲取服務(wù)端的信息,否則不能獲取數(shù)據(jù),即所謂的接口認(rèn)證。
那么這個登錄的狀態(tài),即用戶的認(rèn)證信息,這是怎樣傳給服務(wù)器的呢?
我們會將用戶的認(rèn)證信息包含在前端的請求頭當(dāng)中,發(fā)送給服務(wù)端。
以 get 請求為例,服務(wù)端代碼如下:
const express = require('express') const app = express() app.listen(9000, () => { console.log('http://localhost:9000') }) // 中間件 // 解決跨域 app.use(require('cors')()) // post提供,內(nèi)容為json格式 app.use(express.json()) app.get('/api/users', (req, res) => { // 解決跨域問題 // res.setHeader('Access-Control-Allow-Origin', '*') res.send({ code: 0, msg: 'ok', data: { users: [ { id: 1, name: '張三' }, { id: 2, name: '李四' } ], // 獲取用戶認(rèn)證信息 token: req.headers?.token } }) })
前端代碼如下:
<!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>vue學(xué)習(xí)使用</title> <!-- 第1步: 引入vue庫文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:掛載點(diǎn) --> <div id="app"> <ul> <li v-for="item in users" :key="item.id">{{item.name}}</li> </ul> </div> <!-- 第3步:實例化vue --> <script src="./js/axios.js"></script> <script> // axios全局配置 這里的地址會自動補(bǔ)全到 get 或 post 要請求的地址中 // 可以寫在配置文件中,方便修改 axios.defaults.baseURL = 'http://localhost:9000'; // 全局設(shè)置網(wǎng)絡(luò)請求超時時間,10s中還沒請求到數(shù)據(jù),就停止請求 axios.defaults.timeout = 10000 const vm = new Vue({ el: '#app', data: { users: [] }, mounted() { // 發(fā)送 get 請求 axios.get('/api/users', { // 認(rèn)證信息放在請求頭發(fā)送 headers: { token: 'abc' } }).then(ret => { console.log(ret.data); // 只會監(jiān)聽當(dāng)前 then 方法中是否有異常 }, () => console.log('有異常')) } }) </script> </body> </html>
注意:我們還可以使用全局配置來發(fā)送用戶認(rèn)證信息:axios.defaults.headers.token = 'aaaaa'
,(請求頭中的 token 因該刪掉,否則會覆蓋全局配置)但是這樣的配置會給所有的請求方法都添加上用戶認(rèn)證信息,不能區(qū)別對待,也就是不能進(jìn)行業(yè)務(wù)處理,不夠靈活,所以我們需要用到攔截器。
請求攔截器
延續(xù)上面的案例,如果我們的需求是,如果是 get 方法發(fā)送,則在請求頭中添加用戶認(rèn)證信息,其他方法不添加,則前端頁面需要這樣寫:
<!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>vue學(xué)習(xí)使用</title> <!-- 第1步: 引入vue庫文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:掛載點(diǎn) --> <div id="app"> <ul> <li v-for="item in users" :key="item.id">{{item.name}}</li> </ul> </div> <!-- 第3步:實例化vue --> <script src="./js/axios.js"></script> <script> // axios全局配置 這里的地址會自動補(bǔ)全到 get 或 post 要請求的地址中 // 可以寫在配置文件中,方便修改 axios.defaults.baseURL = 'http://localhost:9000'; // 全局設(shè)置網(wǎng)絡(luò)請求超時時間,10s中還沒請求到數(shù)據(jù),就停止請求 axios.defaults.timeout = 10000 // 請求攔截器 axios.interceptors.request.use(config => { if (config.method === 'get') { config.headers.token = 'abc' } // 請求攔截器中的回調(diào)函數(shù)中的config對象一定要return出去 return config }) const vm = new Vue({ el: '#app', data: { users: [] }, mounted() { // 發(fā)送 get 請求 axios.get('/api/users', { // 認(rèn)證信息放在請求頭發(fā)送 headers: { token: 'abc' } }).then(ret => { console.log(ret.data); // 只會監(jiān)聽當(dāng)前 then 方法中是否有異常 }, () => console.log('有異常')) } }) </script> </body> </html>
注意:請求攔截器中的回調(diào)函數(shù)中的config對象一定要return出去。
響應(yīng)攔截器
作用:
對響應(yīng)的數(shù)據(jù)做處理或判斷
應(yīng)用:
<!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>vue學(xué)習(xí)使用</title> <!-- 第1步: 引入vue庫文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:掛載點(diǎn) --> <div id="app"> <ul> <li v-for="item in users" :key="item.id">{{item.name}}</li> </ul> </div> <!-- 第3步:實例化vue --> <script src="./js/axios.js"></script> <script> // axios全局配置 這里的地址會自動補(bǔ)全到 get 或 post 要請求的地址中 // 可以寫在配置文件中,方便修改 axios.defaults.baseURL = 'http://localhost:9000'; // 全局設(shè)置網(wǎng)絡(luò)請求超時時間,10s中還沒請求到數(shù)據(jù),就停止請求 axios.defaults.timeout = 10000 axios.defaults.headers.token = 'aaaaa' // 響應(yīng)攔截器 axios.interceptors.response.use(res => { // 這里是未被處理過的響應(yīng)數(shù)據(jù) console.log(res); // 解套,減少數(shù)據(jù)的調(diào)用層級,直接返回 res.data if (res.data.code == 0) return res.data // 這里是做了全局的網(wǎng)絡(luò)錯誤處理 alert('有錯') }, err => Promise.reject(err)) const vm = new Vue({ el: '#app', data: { users: [] }, mounted() { // 發(fā)送 get 請求 axios.get('/api/users').then(ret => { // 這里返回的時解套后的數(shù)據(jù)(已經(jīng)被響應(yīng)攔截器處理過了) console.log(ret); // 只會監(jiān)聽當(dāng)前 then 方法中是否有異常 }, () => console.log('有異常')) } }) </script> </body> </html>
用戶管理
服務(wù)端:
// 服務(wù)端代碼:具備增刪改查、數(shù)據(jù)源 const express = require('express') const app = express() app.listen(9000, () => { console.log('http://localhost:9000') }) // 解決跨域 app.use(require('cors')()) // post提供,內(nèi)容為json格式 app.use(express.json()) // 聲明一個變量,只要服務(wù)不重啟,我就永久存儲(放入內(nèi)存了) let users = [ { id: 1, name: '張三', age: 10 }, { id: 2, name: '李四', age: 20 } ] // 響應(yīng)get請求 app.get('/api/users', (req, res) => { res.send({ code: 0, msg: 'ok', // 如果請求成功就返回對應(yīng)的users data: users }) }) // 增添數(shù)據(jù) app.post('/api/users', (req, res) => { // 接受post提交過來的數(shù)據(jù),用當(dāng)前時間作為主鍵id const user = { ...req.body, id: Date.now() } // 添加數(shù)據(jù) users.push(user) res.send({ code: 0, msg: 'ok', // 如果請求成功就返回對應(yīng)的users data: users }) }) // 修改數(shù)據(jù) app.put('/api/users/:id', (req, res) => { // 接受修改的id號 let id = req.params.id // 接受put提交過來的數(shù)據(jù) users = users.map(item => (item.id == id ? { ...item, ...req.body } : item)); res.send({ code: 0, msg: 'ok', data: users }) }) // 刪除數(shù)據(jù) app.delete('/api/users/:id', (req, res) => { // 接受修改的id號 let id = req.params.id users = users.filter(item => item.id != id) res.send({ code: 0, msg: 'ok', data: users }) })
客戶端:
http.js(axios發(fā)送請求):
// 解套處理(響應(yīng)攔截器),直接返回所需數(shù)據(jù),降低層級 axios.interceptors.response.use( res => res.data, err => Promise.reject(err) ) // 請求攔截器 axios.interceptors.request.use( config => { config.baseURL = 'http://localhost:9000' // 請求超時攔截 config.timeout = 10000 return config }, err => Promise.reject(err) ) // 封裝 axios 中的方法 const get = url => axios.get(url) const post = (url, data = {}) => axios.post(url, data) const put = (url, data = {}) => axios.put(url, data) const del = url => axios.delete(url)
index.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>vue學(xué)習(xí)使用</title> </head> <body> <div id="app"> <button @click="add">添加用戶</button> <hr> <ul> <!-- 條件渲染 --> <!-- template標(biāo)簽 影子標(biāo)簽,可以占位,可以讀取指令,但不會被解析成html,可以使有效的標(biāo)簽中沒有不想要的指令 --> <template v-if="users.length===0"> <li>數(shù)據(jù)加載中...</li> </template> <template v-else> <li v-for="item in users" :key="item.id"> <span>{{item.name}}</span> <span> <button @click="edit(item.id)">修改</button> </span> <span> <button @click="del(item.id)">刪除</button> </span> </li> </template> </ul> </div> <script src="./js/vue.js"></script> <script src="./js/axios.js"></script> <script src="./utils/http.js"></script> <script> const vm = new Vue({ el: '#app', data: { // 定義數(shù)據(jù)源 users: [] }, async mounted() { // this.users = await (await get('/api/users')).data let users = await get('/api/users') this.users = users.data }, methods: { async add() { let users = await post(`/api/users`, { name: Date.now() + '' }) this.users = users.data }, async edit(id) { let users = await put(`/api/users/${id}`, { name: Date.now() + '' }) this.users = users.data }, async del(id) { let users = await del(`/api/users/${id}`) this.users = users.data } } }) </script> </body> </html>
到此這篇關(guān)于Vue網(wǎng)絡(luò)請求的三種實現(xiàn)方式介紹的文章就介紹到這了,更多相關(guān)Vue網(wǎng)絡(luò)請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項目中swiper輪播active圖片實現(xiàn)居中并放大
這篇文章主要介紹了vue項目中swiper輪播active圖片實現(xiàn)居中并放大方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05Vue.js結(jié)合bootstrap前端實現(xiàn)分頁和排序效果
這篇文章主要為大家詳細(xì)介紹了Vue.js結(jié)合bootstrap 前端實現(xiàn)分頁和排序效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12Vue中使用vue-i18插件實現(xiàn)多語言切換功能
在基于vue-cli項目開發(fā)過程中,多語言切換功能可使用vue-i18插件,這篇文章分步驟給大家介紹了Vue中使用vue-i18插件實現(xiàn)多語言切換功能,感興趣的朋友一起看看吧2018-04-04