Vue網(wǎng)絡(luò)請(qǐng)求的三種實(shí)現(xiàn)方式介紹
在進(jìn)行 Vue 的網(wǎng)絡(luò)請(qǐng)求之前,我們先寫一些假數(shù)據(jù):
users.json:
[
{ "id": 1, "name": "張三" },
{ "id": 2, "name": "李四" }
]
1.XMLHttpRequest發(fā)送請(qǐng)求
使用 XMLHttpRequest 請(qǐng)求 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ā)送異步請(qǐng)求
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 對(duì)象有一個(gè)屬性 readyState,將其 (xhr.readyState) 打印后發(fā)現(xiàn):進(jìn)入onreadystatechange請(qǐng)求方式中時(shí),可以打印其狀態(tài)為2,狀態(tài)為3,狀態(tài)為4;進(jìn)入onload之后,只出現(xiàn)了狀態(tài)碼4。也就是說,只有處于狀態(tài)碼4,請(qǐng)求已完成,響應(yīng)已就緒的情況下,才會(huì)進(jìn)入onload。只要進(jìn)入onload請(qǐng)求中,一定是已經(jīng)到4這個(gè)狀態(tài)了。nreadystatechange()的定義是只要返回的狀態(tài)碼只要變化時(shí)就回調(diào)一次函數(shù),而onload只有狀態(tài)碼為4時(shí)才能回調(diào)一次函數(shù)。
2.fetch發(fā)送請(qǐng)求
使用 fetch 請(qǐng)求 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請(qǐng)求庫(Vue中推薦寫法)
概述:
Axios 是一個(gè)基于 promise 的 HTTP 庫,可以用在瀏覽器和node.js中。能攔截請(qǐng)求和響應(yīng),自動(dòng)轉(zhuǎn)換JSON數(shù)據(jù)。axios也是vue作者推薦使用的網(wǎng)絡(luò)請(qǐng)求庫。
優(yōu)勢(shì):
- 使用人群多
- 對(duì) Ts 支持非常好
- 跨平臺(tái)(nodejs、移動(dòng)端)
- 基于 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請(qǐng)求
創(chuàng)建自己的服務(wù)器,模擬發(fā)送 get 和 post 請(qǐng)求
步驟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 意味著不會(huì)返回任何數(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全局配置 這里的地址會(huì)自動(dòng)補(bǔ)全到 get 或 post 要請(qǐng)求的地址中
// 可以寫在配置文件中,方便修改
axios.defaults.baseURL = 'http://localhost:9000';
// 全局設(shè)置網(wǎng)絡(luò)請(qǐng)求超時(shí)時(shí)間,10s中還沒請(qǐng)求到數(shù)據(jù),就停止請(qǐng)求
axios.defaults.timeout = 10000
const vm = new Vue({
el: '#app',
data: {
users: []
},
mounted() {
// 發(fā)送 get 請(qǐng)求
// axios.get('/api/users').then(ret => {
// console.log(ret.data);
// // 只會(huì)監(jiān)聽當(dāng)前 then 方法中是否有異常
// }, () => console.log('有異常'))
// 發(fā)送 post 請(qǐng)求
// axios.post('/api/users', {
// name: '李四'
// }).then(ret => {
// console.log(ret.data);
// })
// 發(fā)送 put 請(qǐng)求
// axios.put('/api/users', {
// name: '李四 -- put'
// }).then(ret => {
// console.log(ret.data);
// })
// 發(fā)送 delete 請(qǐng)求
axios.delete('/api/users/100').then(ret => {
console.log(ret.data);
})
}
})
</script>
</body>
</html>注意:
超時(shí)請(qǐng)求不到數(shù)據(jù)就報(bào)出異常,這種捕獲異常的方式,會(huì)監(jiān)聽前面所有的 then 方法
axios.get('/api/users').then(ret => {
console.log(ret.data);
}).catch(() => console.log('有異常'))
下面這種寫法,只會(huì)監(jiān)聽當(dāng)前 then 方法中是否有異常:
axios.get('/api/users').then(ret => {
console.log(ret.data);
},() => console.log('有異常'))
網(wǎng)絡(luò)請(qǐng)求時(shí)發(fā)送用戶認(rèn)證信息
有時(shí)候我們通過網(wǎng)絡(luò)請(qǐng)求一個(gè)服務(wù)器的時(shí)候,需要攜帶一個(gè)用戶認(rèn)證信息,例如用戶只有在登錄狀態(tài)下才能獲取服務(wù)端的信息,否則不能獲取數(shù)據(jù),即所謂的接口認(rèn)證。
那么這個(gè)登錄的狀態(tài),即用戶的認(rèn)證信息,這是怎樣傳給服務(wù)器的呢?
我們會(huì)將用戶的認(rèn)證信息包含在前端的請(qǐng)求頭當(dāng)中,發(fā)送給服務(wù)端。
以 get 請(qǐng)求為例,服務(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全局配置 這里的地址會(huì)自動(dòng)補(bǔ)全到 get 或 post 要請(qǐng)求的地址中
// 可以寫在配置文件中,方便修改
axios.defaults.baseURL = 'http://localhost:9000';
// 全局設(shè)置網(wǎng)絡(luò)請(qǐng)求超時(shí)時(shí)間,10s中還沒請(qǐng)求到數(shù)據(jù),就停止請(qǐng)求
axios.defaults.timeout = 10000
const vm = new Vue({
el: '#app',
data: {
users: []
},
mounted() {
// 發(fā)送 get 請(qǐng)求
axios.get('/api/users', {
// 認(rèn)證信息放在請(qǐng)求頭發(fā)送
headers: {
token: 'abc'
}
}).then(ret => {
console.log(ret.data);
// 只會(huì)監(jiān)聽當(dāng)前 then 方法中是否有異常
}, () => console.log('有異常'))
}
})
</script>
</body>
</html>
注意:我們還可以使用全局配置來發(fā)送用戶認(rèn)證信息:axios.defaults.headers.token = 'aaaaa',(請(qǐng)求頭中的 token 因該刪掉,否則會(huì)覆蓋全局配置)但是這樣的配置會(huì)給所有的請(qǐng)求方法都添加上用戶認(rèn)證信息,不能區(qū)別對(duì)待,也就是不能進(jìn)行業(yè)務(wù)處理,不夠靈活,所以我們需要用到攔截器。
請(qǐng)求攔截器
延續(xù)上面的案例,如果我們的需求是,如果是 get 方法發(fā)送,則在請(qǐng)求頭中添加用戶認(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全局配置 這里的地址會(huì)自動(dòng)補(bǔ)全到 get 或 post 要請(qǐng)求的地址中
// 可以寫在配置文件中,方便修改
axios.defaults.baseURL = 'http://localhost:9000';
// 全局設(shè)置網(wǎng)絡(luò)請(qǐng)求超時(shí)時(shí)間,10s中還沒請(qǐng)求到數(shù)據(jù),就停止請(qǐng)求
axios.defaults.timeout = 10000
// 請(qǐng)求攔截器
axios.interceptors.request.use(config => {
if (config.method === 'get') {
config.headers.token = 'abc'
}
// 請(qǐng)求攔截器中的回調(diào)函數(shù)中的config對(duì)象一定要return出去
return config
})
const vm = new Vue({
el: '#app',
data: {
users: []
},
mounted() {
// 發(fā)送 get 請(qǐng)求
axios.get('/api/users', {
// 認(rèn)證信息放在請(qǐng)求頭發(fā)送
headers: {
token: 'abc'
}
}).then(ret => {
console.log(ret.data);
// 只會(huì)監(jiān)聽當(dāng)前 then 方法中是否有異常
}, () => console.log('有異常'))
}
})
</script>
</body>
</html>
注意:請(qǐng)求攔截器中的回調(diào)函數(shù)中的config對(duì)象一定要return出去。
響應(yīng)攔截器
作用:
對(duì)響應(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全局配置 這里的地址會(huì)自動(dòng)補(bǔ)全到 get 或 post 要請(qǐng)求的地址中
// 可以寫在配置文件中,方便修改
axios.defaults.baseURL = 'http://localhost:9000';
// 全局設(shè)置網(wǎng)絡(luò)請(qǐng)求超時(shí)時(shí)間,10s中還沒請(qǐng)求到數(shù)據(jù),就停止請(qǐng)求
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)用層級(jí),直接返回 res.data
if (res.data.code == 0) return res.data
// 這里是做了全局的網(wǎng)絡(luò)錯(cuò)誤處理
alert('有錯(cuò)')
}, err => Promise.reject(err))
const vm = new Vue({
el: '#app',
data: {
users: []
},
mounted() {
// 發(fā)送 get 請(qǐng)求
axios.get('/api/users').then(ret => {
// 這里返回的時(shí)解套后的數(shù)據(jù)(已經(jīng)被響應(yīng)攔截器處理過了)
console.log(ret);
// 只會(huì)監(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())
// 聲明一個(gè)變量,只要服務(wù)不重啟,我就永久存儲(chǔ)(放入內(nèi)存了)
let users = [
{ id: 1, name: '張三', age: 10 },
{ id: 2, name: '李四', age: 20 }
]
// 響應(yīng)get請(qǐng)求
app.get('/api/users', (req, res) => {
res.send({
code: 0,
msg: 'ok',
// 如果請(qǐng)求成功就返回對(duì)應(yīng)的users
data: users
})
})
// 增添數(shù)據(jù)
app.post('/api/users', (req, res) => {
// 接受post提交過來的數(shù)據(jù),用當(dāng)前時(shí)間作為主鍵id
const user = { ...req.body, id: Date.now() }
// 添加數(shù)據(jù)
users.push(user)
res.send({
code: 0,
msg: 'ok',
// 如果請(qǐng)求成功就返回對(duì)應(yīng)的users
data: users
})
})
// 修改數(shù)據(jù)
app.put('/api/users/:id', (req, res) => {
// 接受修改的id號(hào)
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號(hào)
let id = req.params.id
users = users.filter(item => item.id != id)
res.send({
code: 0,
msg: 'ok',
data: users
})
})客戶端:
http.js(axios發(fā)送請(qǐng)求):
// 解套處理(響應(yīng)攔截器),直接返回所需數(shù)據(jù),降低層級(jí)
axios.interceptors.response.use(
res => res.data,
err => Promise.reject(err)
)
// 請(qǐng)求攔截器
axios.interceptors.request.use(
config => {
config.baseURL = 'http://localhost:9000'
// 請(qǐng)求超時(shí)攔截
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)簽,可以占位,可以讀取指令,但不會(huì)被解析成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ò)請(qǐng)求的三種實(shí)現(xiàn)方式介紹的文章就介紹到這了,更多相關(guān)Vue網(wǎng)絡(luò)請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Vue簡單封裝axios網(wǎng)絡(luò)請(qǐng)求的方法
- Spring Boot + Vue 前后端分離開發(fā)之前端網(wǎng)絡(luò)請(qǐng)求封裝與配置
- Vue3如何使用axios發(fā)起網(wǎng)絡(luò)請(qǐng)求
- vue網(wǎng)絡(luò)請(qǐng)求方案原生網(wǎng)絡(luò)請(qǐng)求和js網(wǎng)絡(luò)請(qǐng)求庫
- 在小程序/mpvue中使用flyio發(fā)起網(wǎng)絡(luò)請(qǐng)求的方法
- 淺談Vue網(wǎng)絡(luò)請(qǐng)求之interceptors實(shí)際應(yīng)用
- Vue項(xiàng)目的網(wǎng)絡(luò)請(qǐng)求代理到封裝步驟詳解
相關(guān)文章
element-ui中select下拉框加載大數(shù)據(jù)渲染優(yōu)化方式
這篇文章主要介紹了element-ui中select下拉框加載大數(shù)據(jù)渲染優(yōu)化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Vue實(shí)現(xiàn)點(diǎn)擊當(dāng)前行變色
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)點(diǎn)擊當(dāng)前行變色,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12
Vue關(guān)于組件化開發(fā)知識(shí)點(diǎn)詳解
在本篇文章里,小編給大家分享的是關(guān)于Vue關(guān)于組件化開發(fā)知識(shí)點(diǎn)詳解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2020-05-05
vue-cli3.X快速創(chuàng)建項(xiàng)目的方法步驟
這篇文章主要介紹了vue-cli3.X快速創(chuàng)建項(xiàng)目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
一個(gè)因@click.stop引發(fā)的bug的解決
這篇文章主要介紹了一個(gè)因@click.stop引發(fā)的bug的解決,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01
vue-cli+webpack項(xiàng)目 修改項(xiàng)目名稱的方法
下面小編就為大家分享一篇vue-cli+webpack項(xiàng)目 修改項(xiàng)目名稱的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-02-02
對(duì)vue中的input輸入框進(jìn)行郵箱驗(yàn)證方式
這篇文章主要介紹了對(duì)vue中的input輸入框進(jìn)行郵箱驗(yàn)證方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10

