新聞中心
一、問題的起源
最近在做vue.js項目時,遇到了vuex狀態(tài)管理action與vue.js方法互相通信、互操作的問題。場景如下圖所示:
樂安網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站開發(fā)等網(wǎng)站項目制作,到程序開發(fā),運(yùn)營維護(hù)。成都創(chuàng)新互聯(lián)從2013年創(chuàng)立到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運(yùn)維經(jīng)驗,來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)。
二、第一種解決方法
例如,我們在頁面初始化的時候,需要從服務(wù)端通過API接口獲取數(shù)據(jù),數(shù)據(jù)獲取成功前需要顯示Loading狀態(tài)框,數(shù)據(jù)獲取完成后,需要將Loading狀態(tài)框隱藏。
這是一種相對比較簡單的應(yīng)用場景,解決起來當(dāng)然也比較簡單。
我們可以通過state數(shù)據(jù)字段來實(shí)現(xiàn)
,在state中存儲一個loading字段,并設(shè)置默認(rèn)值為false。
const store = new Vuex.Store({
state: {
loading: false
},
// ......
});
因為要對state.loading進(jìn)行操作,所以,我們需要定義一個mutation方法,用于更新loading狀態(tài)數(shù)據(jù)。
const UPDATE_LOADING = 'updateLoading';
const store = new Vuex.Store({
// ......,
mutations: {
updateLoading (state, loading) {
state.loading = loading;
}
},
// ......
});
然后,我們聲明一個action方法,用于從HTTP API獲取數(shù)據(jù)。
const store = new Vuex.Store({
// ......,
actions: {
fetchData ({ commit }) {
commit(UPDATE_LOADING, true);
axios.get('...', { params: {...} })
.then(res => {
// TODO 解析HTTP響應(yīng)數(shù)據(jù),進(jìn)行相關(guān)的業(yè)務(wù)邏輯處理
})
.catch(err => {
// TODO 進(jìn)行相關(guān)的錯誤與異常處理
})
.finally(() => {
commit(UPDATE_LOADING, false);
});
}
},
// ......
})
在頁面模板中,我們通過mapActions函數(shù)將vuex的action方法映射為vue.js中對象的方法。
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'fetchData',
// ...
])
}
}
最后,在vue.js的mounted生命周期方法中調(diào)用通過mapActions映身的方法fetchData即可。
export default {
// ...,
mounted() {
this.fetchData();
},
// ...
}
三、第二種解決方法
上述的第一種解決方法,可以通過mutation修改state的狀態(tài)數(shù)據(jù)控制UI上的數(shù)據(jù)渲染。但如果想要將獲取到的結(jié)果數(shù)據(jù)傳到UI組件是不行的,另外,如果想要在調(diào)用action方法執(zhí)行完成后在UI中再去做一些事情也是行不通的。
以前我們知道,異步方法傳遞數(shù)據(jù),可以通過回調(diào)函數(shù)的參數(shù)進(jìn)行傳遞數(shù)據(jù),所以,我提到的第二種解決辦法就是通過回調(diào)函數(shù)實(shí)現(xiàn)
的。
const store = new Vuex.Store({
// ......,
actions: {
fetchData ({ commit }, { params, callback }) {
commit(UPDATE_LOADING, true);
axios.get('...', { params })
.then(res => {
callback(res);
})
.catch(err => {
// TODO 進(jìn)行相關(guān)的錯誤與異常處理
})
.finally(() => {
commit(UPDATE_LOADING, false);
});
}
},
// ......
})
四、第三種解決方法
以上兩種方式雖然可以解決某些問題,但解決方法不夠優(yōu)雅,而且第一種方法具有很大的局限性。比如,不能回調(diào)主界面中的方法執(zhí)行后續(xù)的操作,也不能自由地傳遞參數(shù)。第二種方法采用回調(diào)可以調(diào)用方法,也可以傳參,但callback的調(diào)用是同步方式,代碼風(fēng)格也不是很好。所以,我比較提倡大家使用第三種方法,就是在action調(diào)用時返回一個Promise,這樣在主界面就可以拿到這個promise對象,并進(jìn)行鏈?zhǔn)綀?zhí)行后續(xù)的任務(wù),也可以將action異步任務(wù)的結(jié)果數(shù)據(jù)傳遞給主UI。
const store = new Vuex.Store({
// ......,
actions: {
fetchData ({ commit }, { params }) {
commit(UPDATE_LOADING, true);
return axios.get('...', { params })
.then(res => {
const { data } = res;
return data;
})
.finally(() => {
commit(UPDATE_LOADING, false);
});
}
},
// ......
})
在主UI中,我們就可以采用如下的方式進(jìn)行后續(xù)的操作。
export default {
// ...,
mounted() {
this.fetchData({ id: 1 })
.then(res => {
// TODO 執(zhí)行后續(xù)的任務(wù)
})
.catch(err => {
// TODO 處理異常情況
});
},
// ...
}
文章標(biāo)題:前端技術(shù)之:如何在vuex狀態(tài)管理action異步調(diào)用結(jié)束后執(zhí)行UI中的方法
鏈接URL:http://www.dlmjj.cn/article/iggccj.html