寫在前面
作者簡書地址
axios在實戰(zhàn)項目中的運用,所舉例項目是基于vue全家桶(vue-router+vuex+axios+element-ui)的后臺管理系統(tǒng),需要一些有vue項目開發(fā)經(jīng)驗的讀者閱讀。
由于vue-resource 作者宣布不再更新,促使我們使用第三方的request數(shù)據(jù)請求,一般我們的選擇有
- JQuery ajax
- 本身是針對MVC的編程,不符合現(xiàn)在前端MVVM的浪潮
- 基于原生的XHR開發(fā),XHR本身的架構(gòu)不清晰,已經(jīng)有了fetch的替代方案
- JQuery整個項目太大,單純使用ajax卻要引入整個JQuery非常的不合理(采取個性化打包的方案又不能享受CDN服務(wù))
- fetch
- 符合關(guān)注分離,沒有將輸入、輸出和用事件來跟蹤的狀態(tài)混雜在一個對象里
更好更方便的寫法 - 更加底層,提供的API豐富(request, response)
- 脫離了XHR,是ES規(guī)范里新的實現(xiàn)方式
1)fetchtch只對網(wǎng)絡(luò)請求報錯,對400,500都當做成功的請求,需要封裝去處理
2)fetch默認不會帶cookie,需要添加配置項
3)fetch不支持abort,不支持超時控制,使用setTimeout及Promise.reject的實現(xiàn)的超時控制并不能阻止請求過程繼續(xù)在后臺運行,造成了量的浪費
4)fetch沒有辦法原生監(jiān)測請求的進度,而XHR可以
- axios
- 從瀏覽器中創(chuàng)建 XMLHttpRequest
- 從 node.js 發(fā)出 http 請求
- 支持 Promise API
- 攔截請求和響應(yīng)
- 轉(zhuǎn)換請求和響應(yīng)數(shù)據(jù)
- 取消請求
- 自動轉(zhuǎn)換JSON數(shù)據(jù)
- 客戶端支持防止CSRF/XSRF
題外話(一)
一般在項目中我們會常常遇到跨域的問題,主要受同源策略(協(xié)議,路徑,端口)的影響
尤其是使用vue-cli這種腳手架工具開發(fā)時,由于項目本身啟動本地服務(wù)是需要占用一個端口的,所以必然會產(chǎn)生跨域的問題。
在vue-cli項目中webpack的proxyTable幫我們很好的處理了跨域問題:

如何配置:在項目生成的config目錄下的index.js找
有些項目可能要接不同域名下的接口,而proxyTable支持配置多個域名,有這種需求的小伙伴可以自行配置。
劃下重點------>
axios的請求會在你的url路徑上自動拼接你的target(前提是我這種管理api的方式,后面會提)
記住我畫的那個部分(記住這個配置)
proxyTable: {
'/api/**': {
target: 'http://www.itdecent.cn:8080/', //==>你的目標域名和端口
changeOrigin: true,
pathRewrite: {
'^/': '/'
}
},
}
主題開始
參考axios-中文使用手冊:https://www.kancloud.cn/yunye/axios/234845
一、在我們接Api的時候 主要有兩個階段
- request 請求階段 ===》對應(yīng)了axios.interceptors.request 請求攔截器過濾請求
-
response 響應(yīng)階段 ===》對應(yīng)了axios.interceptors.response 響應(yīng)攔截器過濾響應(yīng)
我一般在項目中建一個API文件夾 統(tǒng)一管理api 以及 axios的request的封裝方法 目錄為下
image.png
下面直接上代碼了:
import axios from 'axios'
import { throwErr } from '@/utils' //utils 捕捉服務(wù)端http狀態(tài)碼的方法
import store from '@/store' //引入vuex的相關(guān)操作
import { Message } from 'element-ui' //element Toast的提示
import router from '@/router'
//過濾請求
axios.interceptors.request.use(config => {
//config 為請求的一些配置 例如:請求頭 請求時間 Token 可以根據(jù)自己的項目需求個性化配置,參考axios的中文說明手冊 自己多動動手
//由于我們項目的后端大大給力,很多東西在服務(wù)端幫我們處理好了所以請求階段只要傳好參數(shù)就好了
config.timeout = 10 * 1000 //請求響應(yīng)時間
return config
}, error => {
return Promise.reject(error)
})
// 添加響應(yīng)攔截器
axios.interceptors.response.use(
response => {
if (response.data.code === 0) { //服務(wù)端定義的響應(yīng)code碼為0時請求成功
return Promise.resolve(response.data) //使用Promise.resolve 正常響應(yīng)
} else if (response.data.code === 1401) { //服務(wù)端定義的響應(yīng)code碼為1401時為未登錄
store.dispatch('setUserInfo', {})
Message({
message: '未登錄'
})
// router.push('/login')
return Promise.reject(response.data) //使用Promise.reject 拋出錯誤和異常
} else {
return Promise.reject(response.data)
}
},
error => {
if (error && error.response) {
let res = {}
res.code = error.response.status
res.msg = throwErr(error.response.status, error.response) //throwErr 捕捉服務(wù)端的http狀態(tài)碼 定義在utils工具類的方法
return Promise.reject(res)
}
return Promise.reject(error)
}
)
export default function request(method, url, data) { //暴露 request 給我們好API 管理
method = method.toLocaleLowerCase() //封裝RESTful API的各種請求方式 以 post get delete為例
if (method === 'post') {
return axios.post(url, data) //axios的post 默認轉(zhuǎn)化為json格式
} else if (method === 'get') {
return axios.get(url, {
params: data
})
} else if (method === 'delete') {
return axios.delete(url, {
params: data
})
}
}
以下為throwErr的源碼
//axios捕錯
export const throwErr = (code, response) => {
let message = '請求錯誤'
switch (code) {
case 400:
message = '請求錯誤'
break
case 401:
message = '未授權(quán),請登錄'
break
case 403:
message = '拒絕訪問'
break
case 404:
message = `請求地址出錯: ${response.config.url}`
break
case 408:
message = '請求超時'
break
case 500:
message = '服務(wù)器內(nèi)部錯誤'
break
case 501:
message = '服務(wù)未實現(xiàn)'
break
case 502:
message = '網(wǎng)關(guān)錯誤'
break
case 503:
message = '服務(wù)不可用'
break
case 504:
message = '網(wǎng)關(guān)超時'
break
case 505:
message = 'HTTP版本不受支持'
break
default:
}
return message
}
如果有的小伙伴 是'application/x-www-form-urlencoded'為請求格式的話
可以使用 npm i qs -S 使用qs包將參數(shù)序列化
transformRequest:[function(data){
//在這里根據(jù)自己的需求改變數(shù)據(jù)
return qs.stringify(data,{arrayFormat:'repeat'})
}],
二 在api管理文件夾中如何定義接口呢?
以account.js為例
- 引入request.js
- 暴露你定義的api接口
- request 的三個參數(shù)(mtehod,url,params)
- method 及axios的請求方法 (post,get,delete ···?)
- url 服務(wù)端的接口路徑
3.params 接口所傳遞的參數(shù) 全部以對象的形式傳入 (后面會提 不著急)

import request from './request' //引入axios的封裝方法
export const getAdminList = (params) => {
return request('get', '/api/v1.0/admin/list', params) //登陸管理員獲取自身信息
}
export const register = (params) => {
return request('post', '/api/v1.0/admin/register', params) //添加管理員
}
export const deleteAdmin = (id, params) => {
return request('delete', `/api/v1.0/admin/${id}`, params) //更新管理員信息
}
是不是很簡單 管理的接口就是這么簡潔帥氣 為我打個call
在項目中如何使用定義的接口?
1.在頁面中import對應(yīng)的模塊api文件以及其中的接口
2.不管是哪種請求 我們?nèi)坑脤ο螅ㄦI值對)的形式傳參數(shù)
3.用async 和await 在methods中定義接口方法
- 用來區(qū)分我們所定義的普通方法
- 可以方便我們處理函數(shù)回調(diào) 用同步的思想寫代碼 方便理解
- 不用.then那種鏈式寫法 美化代碼 增加可讀性和理解性
- 配合try catch用來捕錯

此例子可以在我的上篇關(guān)于 vue mixin的文章結(jié)合觀看 觀碼效果更加
傳送門
getParams() {
return {
role: this.role,
name: this.name,
status: this.status,
start: (this.PAGINATION.currentPage - 1) * this.PAGINATION.pageSize,
range: this.PAGINATION.pageSize,
}
},
async getAdminList() {
this.loading = true
let res = await getAdminList(this.queryParams)
this.tableData = res.data.list
this.PAGINATION.total = res.data.count
this.loading = false
},
async deleteAdmin() {
try {
let res = await deleteAdmin(this.id)
this.$message({
type: 'success',
message: '刪除成功'
})
this.getAdminList()
} catch (err) {
this.$message({
type: 'error',
message: err.msg
})
}
},
addParams() {
let { role, username, name, password, gender, profession, education, signature } = this.form
return { role, username, name, password, gender, profession, education, signature }
},
async register() {
try {
let res = await register({ ...this.addParams() })
this.$message({
type: 'success',
message: '添加成功'
})
this.dialogFormVisible = false
this.$emit('listen')
} catch (err) {
this.$message({
type: 'error',
message: err.msg
})
}
},
在實際表現(xiàn)如下
1.get 操作表現(xiàn)

2.delete操作表現(xiàn)

3.post 操作

題外話(二)
關(guān)于RESTful API的理解 (主要是后端開發(fā)者觀看,前端小伙伴了解即可)
精簡點:
- http的動詞(get post delete put patch ···)描述操作
- url地址定位資源
RESTful API:
這是一種設(shè)計風格而不是標準,只是提供了一組設(shè)計原則和約束條件。它主要用于客戶端與服務(wù)器交互類的軟件?;谶@個風格設(shè)計的軟件可以更簡潔,更有層級,更易于實現(xiàn)緩存等機制。在這種風格中,每個url路徑代表一種資源(resource),所以路徑中不推薦有名詞,而且所用的名詞往往與數(shù)據(jù)庫的表格名對應(yīng),且一般采取復數(shù)的形式命名。而對應(yīng)資源的具體操作類型,而由HTTP動詞表示,即 GET/POST/PUT/PATCH/DELETE

這是我在看書過程中所閱讀到的,具體書名就不透露了,免得有打廣告嫌疑
寫在后面
以上就是axios的二次封裝如何在項目中如何優(yōu)雅的使用,統(tǒng)一使用對象傳參的方式。我覺得這種方式很方便優(yōu)雅,因此將它分享出來,希望大家會喜歡。覺得有用的小伙伴可以給個心,給個關(guān)注,有不懂的地方可以評論我和私信我,有空會一一解答。下次會分享一篇在vue中如何將tinyMce封裝成組件,tinyMCe富文本編輯器如何上傳圖片和文件。
簡書首發(fā)網(wǎng)址
