在上一篇利用vue-cli + vant搭建一個移動端開發模板的小文章中,我們簡易的搭建了一個使適用於h5開發的模板,很多細節的地方都是一帶而過。所以這邊短文會以圖文的形式,為大家展示vue項目開發過程中,從請求接口到頁面獲取數據,這一系列的流程中(請求接口、axios攔截、狀態管理、異常處理等)具體做了些什么。
源碼地址 (master分支為最新代碼,本文分支為2020/06/17)
流程圖
流程圖參考了vuex官網
一、Dispatch。
使用mapActions將store中我們需要的actions注入到組件中 (views\About.vue)
import { mapActions } from "vuex";
export default {
created() {
const parameter = {id: 1}
this.getSomeData(parameter);
},
methods: {
...mapActions("some", ["getSomeData"])
}
};
二、Action執行異步操作
在此Action中,執行請求接口的方法 (store\modules\some.js)
async getSomeData({ commit }, parameter) {
console.log(parameter)
const response = await getSomeDataApi(parameter)
}
三、通過二次封裝的axios請求接口
我們通過二次封裝axios,將公共的請求攔截,異常處理、請求頭等封裝起來統一操作。 (api\some.js)
import { axios } from '@/utils/request'
export function getSomeDataApi(parameter) {
return axios({
url: '/detail',
method: 'get',
params: parameter
})
}
utils\request下對axios進行二次封裝
import axios from 'axios'
import { errorCode } from './errorCode'
// 創建 axios 實例
const service = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL, // api base_url
timeout: 6000 // 請求超時時間
})
// 在異常處理中,我們可以 根據error.response.status返回的狀態碼進行操作,比如接口返回401作權限操作等
const err = (error) => {
if (error.response) {
if (error.response.status !== 200) {
// 接口接口返回的狀態碼,獲取對應的提示消息
const errorMessage = errorCode(error.response)
console.log(errorMessage)
return
}
}
return Promise.reject(error)
}
// 請求攔截中,我們可以對請求頭作處理,比如所有的請求都加一個token等
service.interceptors.request.use(config => {
// const token = 'token'
// if (token) {
// config.headers['Access-Token'] = token // 讓每個請求攜帶自定義 token 請根據實際情況自行修改
// }
return config
}, err)
// 返回數據攔截中,我們可以對數據做一些小小的處理,比如后端所有接口返回的數據是這種類型:{data: {...}},那我們就可以把data這一層給過濾掉
service.interceptors.response.use((response) => {
return response.data
}, err)
export {
service as axios
}
上述代碼中,有個baseURL,其值我們可以通過.env這個文件中得到,這個玩意的作用相當於在所有的請求前加一個公共的地址。舉個例子:所有的接口前都需要加一個/api來供后台接口做轉發,我們肯定不會在所有的接口前一個一個加,那樣費事又費力,這個時候我們就可以用到baseURL了。
四、獲得返回的數據
我們在獲取數據后,如果想立刻獲得結果,可以通過傳遞一個callback參數的形式,從Action里callback到組件中。
1、修改Some.vue,添加callback參數
import { mapActions } from "vuex";
export default {
created() {
const parameter = {id: 1}
this.getSomeData(parameter);
this.doSomeCallback({
parameter,
callback: res => {
console.log('這里是actions里callback回來的數據' + res)
}
});
},
methods: {
...mapActions("some", ["getSomeData", "doSomeCallback"])
}
};
2、修改store\modules\some.js
async doSomeCallback({ commit }, { parameter, callback })
const response = await getSomeDataApi(parameter)
if (callback) callback(response)
}
五、Commit
在Action里獲取到接口返回的數據時,我們可以通過commit這個方法,執行Mutation。修改store\modules\some.js
import { getSomeDataApi } from '@/api/some'
const mutations = {
setSomeData: (state, data) => {
console.log(data)
}
}
const actions = {
async getSomeData({ commit }, parameter) {
console.log(parameter)
const response = await getSomeDataApi(parameter)
commit('setSomeData', response)
},
async doSomeCallback({ commit }, { parameter, callback }) {
console.log(parameter)
const response = await getSomeDataApi(parameter)
commit('setSomeData', response)
if (callback) callback(response)
},
}
六、Mutate
更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。我們在獲取數據后,修改state里的值。最終store\modules\some.js的代碼
import { getSomeDataApi } from '@/api/some'
const state = {
someData: ''
}
const mutations = {
setSomeData: (state, data) => {
// 為了演示效果我加了個Math.random()
state.someData = data ? data : Math.random()
}
}
const actions = {
async getSomeData({ commit }, parameter) {
console.log(parameter)
const response = await getSomeDataApi(parameter)
commit('setSomeData', response)
},
async doSomeCallback({ commit }, { parameter, callback }) {
console.log(parameter)
const response = await getSomeDataApi(parameter)
commit('setSomeData', response)
if (callback) callback(response)
},
}
export default {
namespaced: true,
state,
mutations,
actions
}
七、Render
在state里的值修改后,我們組件中綁定綁定的值如果改變了,頁面就會更新。修改Some.vue。
import { mapState } from "vuex";
computed: {
...mapState("some", ["someData"])
}
<div class="about">
{{someData}}
</div>
最終我們的Some.vue的代碼如下所示
<template>
<div class="about">
<router-link to="/">Home</router-link>
<Button type="primary" @click="doSomeCallback">點擊修改state里的值</Button>
{{someData}}
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
import { Button } from "vant";
export default {
computed: {
...mapState("some", ["someData"])
},
created() {
const parameter = { id: 1 };
this.getSomeData(parameter);
this.doSomeCallback({
parameter,
callback: res => {
console.log("這里是actions里callback回來的數據" + res);
}
});
},
methods: {
...mapActions("some", ["getSomeData", "doSomeCallback"])
},
components: {
Button
}
};
</script>
<style lang="less">
.about {
height: 100vh;
font-size: 14px;
}
#detail {
font-size: 14px;
}
</style>
vuex使用的注意點
優點:如果所有的接口走都vuex管理的話,有固定的流程,比較條理清晰,便於維護。
缺點:因為組件以及數據過多的情況,vuex內的數據也會越來越大,內存的占用也會越來愈大。
比較常用的使用vuex的情況:多個組件使用共同的接口數據(如后台管理某個下拉框的數據),應用的狀態管理(如h5應用內存儲用戶數據)等。。。
具體的可參考 一張圖弄明白 Vuex 里該存放什么樣的數據。 Should I Store This Data in Vuex – When Should I use Vuex?
總結
以上通過請求接口到頁面更新這一流程,向您展示了如何在項目里管理好axios請求與vuex。因本人文筆不太行,文章中可能會出現一些語句混亂的情況,望您諒解。(源碼在文章開頭)
感謝你的閱讀,如有修改或者建議的地方,歡迎提出哦。