前言:前些日子讀文章,說是vue3.0會在明年下半年正式推出,改動的地方好像也不少,比如說vue3.x的程式碼庫將會用typescript編寫,並提供改進的 TypeScript 支援.變化還是很快的,雖然水平還差的遠,可路還是一步一步走吧.ok,回到正題,在vue2.x的版本中請求資料推薦使用的axios,之前我常常使用的axios的別名方法,比如說在vue元件中:
axios.get('http://localhost:3000/user')
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
複製程式碼
如果一個頁面發多個請求,那寫法上還是比較麻煩的,並沒有async,await的寫法清爽,也沒有體現出所謂物件導向程式設計啊,es6中類的思想和優勢.所以文章分三部分,一部分是axios的二次封裝,另一部分是async,await的使用,再一部分是對別人的借鑑!
axios的二次封裝
以vue2.x的webpack為例說明
src資料夾結構目錄
基礎原理
使用axios去自定義建立例項,掛載請求所需配置項
axios.create([config])
//抄來的案例
const instance = axios.create({
baseURL: 'http://exemple.com/api/',
timeout: 1000,
header: {'X-Custom-Header': 'foobar'}
})
複製程式碼
檔案說明
config資料夾下的url.js檔案
// axios請求的預設請求地址,區分生產環境與開發環境
// 題外話,vue2.x專案中會有伺服器代理的配置項(上篇文章有提及)
// 此處的的axios的預設地址會拼接在代理配置項的基地址之後
// 所以呢,結合實際情況設定axios的預設請求地址
export const baseURL = process.env.NODE_ENV === 'production'
? '/production'
: '/development'
複製程式碼
libs資料夾下的axios.js檔案
import axios from 'axios'
import {baseURL} from '@/config/url'
// 主要是在處理put,post等請求的傳參情況
// 有時後端會需要將傳遞的物件引數轉化成urlcode的形式
// qs就能發揮相應的作用
import qs from 'qs'
// es6當中類的一個寫法,物件導向思想的一個體現
// 不明白自行查資料哦
class HttpRequest {
constructor (baseUrl = baseURL) {
this.baseUrl = baseUrl
}
// 設定axios的請求例項的預設配置項
getInsideConfig () {
const config = {
baseUrl: this.baseUrl,
headers: {
//
}
}
return config
}
// axios的攔截器
interceptors (instance) {
// 請求攔截器(比如在此處驗證一下是否有發請求的許可權)
instance.interceptors.request.use(config => {
return config
}, error => {
return Promise.reject(error)
})
// 響應攔截器
// (比如對返回的引數做一些處理,比如請求狀態的提示語的處理)
// (拿data中的資料,response物件可能是有很多層data的)
instance.interceptors.response.use(res => {
return res
}, err => {
return Promise.reject(err)
})
}
// 此處即為建立請求例項,真正在請求中發揮作用的地方
create (options) {
if (options.method === 'post' || options.method === 'put') {
options.headers['Content-Type'] = 'application/x-www-form-urlencoded'
// post,put請求需要將傳遞的資料掛載在data項上
// 後臺需要傳遞引數urlcode化/引數序列化時,使用qs
options.data = qs.stringify(options.data)
} else {
// get等請求的資料掛在params項上,當然params項上也可以掛post等請求的引數,
// 但是不嚴謹,且引數拼接到位址列上也不安全,有長度限制
options.params = options.data
}
return axios.create(options)
}
// 暴露到其他檔案中被使用的方法,options引數也是外部檔案傳遞進來的
request (options) {
// Object.assign返回一個將引數物件的屬性合併後的一個物件
options = Object.assign(this.getInsideConfig(), options)
const instance = this.create(options)
this.interceptors(instance)
return instance(options)
}
}
export default HttpRequest
複製程式碼
libs資料夾下axiosRequest.js檔案
// 實際上本檔案只是起了一箇中轉作用,一個類的實現或者叫例項化
import HttpRequest from '@/libs/axios'
const axios = new HttpRequest()
export default axios
複製程式碼
api資料夾下order.js檔案
// system.js是系統設定模組的一些請求方法
// 訂單模組,請求方法的集中處理
import axios from '@/libs/axiosRequest'
// 獲取訂單列表(重新整理頁面時,進入的是未處理訂單)
export const getOrderList = (getData) => {
const data = {
page: getData.page,
rows: getData.rows,
orderStatus: getData.orderStatus,
keyWord: getData.keyWord
}
return axios.request({
url: '/carscraporder-manager/order',
data,
method: 'get'
})
}
// 獲取訂單詳情
export const getOrderDetail = (id) => {
return axios.request({
url: `/carscraporder-manager/order/${id}`,
method: 'get'
})
}
// 舊件訂單派單異常
export const abnormalPartOrder = (id, data) => {
return axios.request({
url: `/carscraporder-manager/order/audit/${id}`,
data,
method: 'put'
})
}
複製程式碼
async,await的使用
views資料夾下Order.vue檔案
// 按需引入請求方法
<script>
import { getOrderList, getHistoryOrderList, getAllOrderList, getOrderDetail } from '@/api/order'
export default {
data() {
return {
// 判定當前所要查詢的訂單狀態,預設1為未處理,2為已處理,3為全部
orderState: 1,
// 要傳遞給舊件編輯頁面的表單資料
partOrderDetail: {},
// 要傳遞給整車編輯頁面的表單資料
newOrderdetail: {},
tableData: [],
query: '',
pagenum: 1,
total: 0,
// 舊件編輯頁面開關變數
partEditvisible: false,
// 整車編輯頁面開關變數
allEditvisible: false,
options: [],
currentRoleId: -1
}
},
methods: {
// 全部訂單
async allOrderList () {
this.pagenum = 1
this.orderState = 3
let data = {
page: 1,
rows: 10
}
const response = await getAllOrderList(data)
if (response.data.code === 200) {
this.tableData = response.data.data.rows
this.total = response.data.data.total
} else {
this.$message.error('全部訂單列表獲取失敗')
}
},
}
}
</script>
複製程式碼
別人的一些觀點和優化
- 響應攔截時錯誤http狀態碼的處理
//axios捕錯,需要引入的一個檔案
export const throwErr = (code, response) => {
let message = '請求錯誤'
switch (code) {
case 400:
message = '請求錯誤'
break
case 401:
message = '未授權,請登入'
break
case 403:
message = '拒絕訪問'
break
case 404:
message = `請求地址出錯: ${response.config.url}`
break
case 408:
message = '請求超時'
break
case 500:
message = '伺服器內部錯誤'
break
case 501:
message = '服務未實現'
break
case 502:
message = '閘道器錯誤'
break
case 503:
message = '服務不可用'
break
case 504:
message = '閘道器超時'
break
case 505:
message = 'HTTP版本不受支援'
break
default:
}
return message
}
複製程式碼
- 響應之後銷燬請求例項
class httpRequest {
constructor () {
// 儲存請求佇列
this.queue = {};
}
// 銷燬請求例項
destroy (url) {
delete this.queue[url];
// Object.keys:屬性名字串組成的一個陣列
const queue = Object.keys(this.queue);
return queue.length;
}
interceptors (instance, url) {
instance.interceptors.response.use((res) => {
let { data } = res;
this.destroy(url);
}
}
// 請求例項
request (options) {
var instance = this.create(options);
// url為屬性名,instance為屬性值
this.queue[options.url] = instance;
}
複製程式碼