如何在Vue項(xiàng)目中使用axios請求
在實(shí)際的項(xiàng)目中,和后臺的數(shù)據(jù)交互是少不了的,我通常使用的是 axios 庫,所以以下示例也是以 axios 為基礎(chǔ)來進(jìn)行封裝的。
1、安裝
首先是 npm 安裝 axios 很簡單:npm install axios
2、沒有封裝存在的問題
如果在沒有封裝接口的項(xiàng)目中,在文件中隨處可以看到如下的接口調(diào)用方法:
this.$axios.post("/user/add", {
params: {
name: this.name,
age: this.age
}
})
.then(res => {
console.log(res)
})
.then(err => {
console.log(res)
})
這樣寫不是不可以,但是存在一些缺陷,接口請求的 url 散布在各個文件中,如果需要在接口調(diào)用成功或失敗時(shí)做一些處理,就需要更改每個文件。所以把這些接口請求統(tǒng)一集中起來,如果有調(diào)整,直接在集中文件中找到修改就好了,而不用再去查每個文件。
3、創(chuàng)建文件
首先在項(xiàng)目的 src 目錄中,新建文件夾及文件目錄結(jié)構(gòu)如下:
├── src 源碼目錄
│ ├── apis 接口文件目錄
│ │ ├── login.api.js 登錄模塊的接口 api
│ │ └── user.api.js 用戶模塊的接口 api
│ ├── services 請求相關(guān)文件目錄
│ │ ├── address.js 請求地址配置文件
│ │ └── request.js axios封裝,請求攔截、響應(yīng)碼處理等操作
api接口文件模塊的劃分,大可以根據(jù)自己的實(shí)際項(xiàng)目,按業(yè)務(wù)功能或業(yè)務(wù)邏輯或其他形式劃分。
4、請求地址配置
一般我們的項(xiàng)目環(huán)境都會有多個,少的也會有開發(fā)環(huán)境和生產(chǎn)環(huán)境。正常情況下,在開發(fā)環(huán)境下和生產(chǎn)模式下有著不同的 baseURL,所以,我們需要根據(jù)不同的環(huán)境切換不同的 baseURL。
address.js 文件:
// 根據(jù) process.env.NODE_ENV 切換不同的 baseURL
const isPro = process.env.NODE_ENV === 'production'
module.exports = {
// 'apis':vue.config.js中proxy設(shè)置的代理
baseURL: isPro ? 'http://192.168.100.120/ceds' : '/apis'
}
5、axios 配置,設(shè)置請求頭及響應(yīng)碼處理
大體思路是通過封裝一個request類,其中包含了get、post等請求方法,這些請求方法又都會去調(diào)用 request 方法,該方法通過傳入的不同參數(shù)調(diào)用原始的 axios 請求,然后返回一個 Promise。
request.js 文件:
import axios from 'axios'
import Qs from 'qs'
import Vue from 'vue'
import { getToken } from '@Utils/session.utils' // 存儲獲取token文件
import address from './address' // 請求地址
class Request {
constructor () {
// 創(chuàng)建axios實(shí)例
this._axios = axios.create({
baseURL: address.baseURL,
timeout: 1000 * 5, // 請求超時(shí)時(shí)間
headers: {}
})
// 請求攔截
this._axios.interceptors.request.use(
config => {
const requestHeader = {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json; charset=UTF-8',
'Access-Control-Allow-Origin': '*',
token: getToken() // 請求頭統(tǒng)一添加token
}
config.headers = Object.assign(config.headers, requestHeader)
return config
},
error => {
Promise.reject(error)
}
)
}
// 根據(jù)請求方式,判斷參數(shù)是放在query中還是body中。
// 最直觀的區(qū)別,比如GET請求把參數(shù)包含在url中,而POST則通過request body把參數(shù)放置在body體中,所以在提交時(shí)的參數(shù)形式是有區(qū)別的
// 以下列了四種我一般常用請求方式的參數(shù)形式,大家可以自行調(diào)整
/**
* 發(fā)送get請求
* @param {String} url地址
* @param {Object} query 查詢參數(shù)
* @return json數(shù)據(jù)
*/
get (url, query = {}) {
return this._request('get')(url, {
...query
})
}
/**
* 發(fā)送post請求
* @param {String} url地址
* @param {Object} body 查詢參數(shù)
* @return json數(shù)據(jù)
*/
post(url, body = {}, headers) {
let data;
if(this.isFormData(body)) {
data = body
} else if(Array.isArray(body)) {
data = body
} else {
data = { ...body }
}
return this._request('post')(url, headers)(url, data);
}
put (url, body = {}) {
return this._request('put')(url, {
...body
});
}
delete(url, body = {}) {
return this._request('delete')(url, {
...body
});
}
isFormData = v => {
return Object.prototype.toString.call(v) === '[object FormData]'
}
/**
* 設(shè)置請求頭
* @param {Object} header 請求頭
*/
setHeaders (header) {
Object.keys(header).forEach(key => {
this._axios.defaults.headers[key] = header[key]
})
}
// 處理請求頭 headers
handleHeaders () {
const headers = {}
headers['XMIME-TYPE'] = '3'
Headers['Content-Type'] = 'application/json; charset=UTF-8'
return headers
}
/**
* 發(fā)送請求
* @param {String} method 請求方法類型
* @param headers
* @returns {function(*=, *=):Promise<unknown>}
* @private
*/
_request (method, headers) {
this.setHeaders(this.handleHeaders()) // 設(shè)置統(tǒng)一的請求頭
if (headers) {
this.setHeaders(headers) // 自定義請求頭
}
return (url, data, timeout) => {
const config = {
url,
method,
timeout: timeout || this._axios.defaults.timeout
} // 構(gòu)造請求 config
// 判斷請求類型 get post
const paramType = ['get', 'delete'].indexOf(method) !== -1 ? 'params' : 'data'
config[paramType] = data
//參數(shù)序列化
config.paramsSerializer = params => {
return Qs.stringify(params, { arrayFormat: 'repeat' });
}
return new Promise((resolve, reject) => {
// 發(fā)送真正的請求,驗(yàn)證權(quán)限,檢查404等status
this._axios
.request(config)
.then(response => {
if (this.handleSuccessStatus(response.data.code, response.data)) {
if (response.headers['content-type'] !== 'text/plain; charset=urf-8') {
resolve(
// 對響應(yīng)結(jié)果二次包裝
Object.assign(
{
success: Number(response.data.code) === 200,
data: response.data.data,
msg: response.data.msg
},
response.data
)
) // 處理返回結(jié)果
} else {
resolve(response.data)
}
}
}, response => {
// 處理錯誤碼
if(response.response) {
const statusCode = response.response.status
this.handleErrorStatus(statusCode)
} else {
Vue.prototype.$message.error(response.message)
}
reject(response)
})
.catch(err => {
reject(err)
})
})
}
}
}
// 請求成功,返回錯誤碼
// 具體狀態(tài)碼跟后臺開發(fā)人員統(tǒng)一,然后根據(jù)狀態(tài)碼進(jìn)行相應(yīng)提示
// 下面是我在項(xiàng)目中的操作,大家可自行調(diào)整擴(kuò)展
handleSuccessStatus (code, data) {
let result = ''
let flag = false
switch (code) {
case '20007':
result = '未查找到二次認(rèn)證密碼!'
flag = true
break
case '20008':
result = '您的二次認(rèn)證密碼還未修改,請先修改!'
flag = true
break
case '20009':
result = '您還未開啟二次認(rèn)證,請聯(lián)系管理員!'
flag = true
break
case '90001':
result = '請輸入二次認(rèn)證密碼!'
flag = true
break
case '90002':
result = '無操作權(quán)限!'
flag = true
break
default:
break
}
// 進(jìn)行通知
// $message方法是我按需引入的element-ui中的提示組件,你可以替換成自己的提示組件
if (result) {
Vue.prototype.$message.error(result)
}
return flag
}
// 根據(jù)錯誤碼獲取錯誤提示
handleErrorStatus (statusCode) {
let errorMsg = ''
if (statusCode === 500) {
errorMsg = '數(shù)據(jù)請求失敗,請聯(lián)系管理員!'
} else if (statusCode === 404) {
errorMsg = '請求地址錯誤!'
} else if (statusCode === 402) {
errorMsg = '當(dāng)前您沒有權(quán)限操作該數(shù)據(jù)!'
} else {
errorMsg = '請求出錯!'
}
// 進(jìn)行通知
Vue.prototype.$message.error(errorMsg)
}
}
export default new Request()
6、使用
我們在接口管理文件中,通過調(diào)用上面封裝的 request 類,傳入對應(yīng)的參數(shù)即可。
user.api.js 文件:
import http from '../services/request'
/**
* @description 獲取用戶列表
* @param {*} params 請求接口的參數(shù)
*/
// 此處定義的reqUserList方法會調(diào)用我們封裝的request中的get方法,get方法的第一個參數(shù)是請求地址,第二參數(shù)是query參數(shù)
export const reqUserList = params => http.get('/user/list', params)
在調(diào)用的 .vue 文件中,引入該方法并傳入?yún)?shù)即可
import { reqUserList } from '@Apis/user.api' // 導(dǎo)入api
export default {
name: 'UserList',
... ...
created() {
},
methods: {
async getUsers() {
// 調(diào)用api接口,并傳入?yún)?shù)
const res = await reqUserList({
page: 1,
size: 10
})
console.log(res) // 獲取的響應(yīng)結(jié)果
}
}
}
如此,就完成了對接口的封裝及基本使用。
PS:以上這些文件名、文件夾名、方法名、路徑等都是我自己取得,你可以按照自己的代碼風(fēng)格習(xí)慣進(jìn)行調(diào)整。
以上就是如何在Vue項(xiàng)目中使用axios請求的詳細(xì)內(nèi)容,更多關(guān)于Vue項(xiàng)目中使用axios的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue實(shí)現(xiàn)多個el-form表單提交統(tǒng)一校驗(yàn)的2個方法
這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)多個el-form表單提交統(tǒng)一校驗(yàn)的2個方法,文中通過代碼示例介紹的非常詳細(xì),對大家學(xué)習(xí)或使用vue具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
Vue數(shù)據(jù)變了但頁面沒有變的幾種情況及解決方法
如果,你發(fā)現(xiàn)自己需要在Vue中做一次強(qiáng)制更新,99.99%的情況,是你在某個地方做錯了事,本文給大家就介紹了Vue數(shù)據(jù)變了,但頁面沒有變的幾種情況及解決方法,并通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2024-08-08
關(guān)于element-ui?select?下拉框位置錯亂問題解決
這篇文章主要介紹了關(guān)于element-ui?select?下拉框位置錯亂問題解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
vue路由跳轉(zhuǎn)router-link清除歷史記錄的三種方式(總結(jié))
這篇文章主要介紹了vue路由跳轉(zhuǎn)router-link清除歷史記錄的三種方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04
Vue全局共享數(shù)據(jù)之globalData,vuex,本地存儲的使用
這篇文章主要介紹了Vue全局共享數(shù)據(jù)之globalData,vuex,本地存儲的使用方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10
Vue 讀取HTMLCollection列表的length為0問題
這篇文章主要介紹了Vue 讀取HTMLCollection列表的length為0問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
Vue設(shè)置select下拉框的默認(rèn)選項(xiàng)詳解(select空白bug解決)
最近開始學(xué)習(xí)vue,在學(xué)習(xí)的過程中遇到的問題將記錄在這里,下面這篇文章主要給大家介紹了關(guān)于Vue設(shè)置select下拉框的默認(rèn)選項(xiàng)(select空白bug解決)的相關(guān)資料,需要的朋友可以參考下2022-12-12

