Vue網(wǎng)絡(luò)請求的三種實(shí)現(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步:實(shí)例化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步:實(shí)例化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步:實(shí)例化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步:實(shí)例化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ò)請求的三種實(shí)現(xiàn)方式介紹的文章就介紹到這了,更多相關(guān)Vue網(wǎng)絡(luò)請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue項(xiàng)目中ESlint規(guī)范示例代碼
這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中ESlint規(guī)范的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
vue項(xiàng)目中swiper輪播active圖片實(shí)現(xiàn)居中并放大
這篇文章主要介紹了vue項(xiàng)目中swiper輪播active圖片實(shí)現(xiàn)居中并放大方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05
Vue.js結(jié)合bootstrap前端實(shí)現(xiàn)分頁和排序效果
這篇文章主要為大家詳細(xì)介紹了Vue.js結(jié)合bootstrap 前端實(shí)現(xiàn)分頁和排序效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12
Vue中使用vue-i18插件實(shí)現(xiàn)多語言切換功能
在基于vue-cli項(xiàng)目開發(fā)過程中,多語言切換功能可使用vue-i18插件,這篇文章分步驟給大家介紹了Vue中使用vue-i18插件實(shí)現(xiàn)多語言切換功能,感興趣的朋友一起看看吧2018-04-04

