vuex解决项目中loading问题
使用场景
项目中发起请求,难免会需要用到loading,如果我们直接使用拦截器拦截请求的发起以及响应,会导致整个项目中所有的请求公用一个状态。
如果我们需要控制每一个请求的loading状态那就非常完美了
先看效果
初设
为解决这个问题,我们可以使用vuex,在所有的action中设置与当前action同名的loading状态,如下
// 此函数用于模拟ajax请求,返回一个promise,将会在2s后成功import{ axiosTwo }from'@/utils/http'import{ createStore }from'vuex'exportdefaultcreateStore({
state:{// 存储当前模块中所有的loading
loading:{}},
mutations:{// 保存loading状态到状态(state)中setLoading(state,{ name, isLoading }){
state.loading[name]= isLoading
}},
actions:{asyncgetList(context){// 设置loading状态为true
context.commit('setLoading',{
name:'getList',
isLoading:true})awaitaxiosTwo()
console.log('请求完成')// 设置loading状态
context.commit('setLoading',{
name:'getList',
isLoading:false})}}})
但是这样的话我们每个action都要重复的写上这块代码,非常不友好,容易累死,所以我们可以做一个工厂函数,让每一个经过我这里的action都变成这个样子就完美了
plus版
// 用于生成带有loading的actionsfunctioncreateActions(actions){// 用于记录装修过的actionsconst newActions ={}// 循环所有的actionfor(const fnName in actions){if(Object.hasOwnProperty.call(actions, fnName)){const action = actions[fnName]// 存储新的action
newActions[fnName]=asyncfunction(context, payload){// 在这个新的action中设置loading状态
context.commit('setLoading',{
name: fnName,
isLoading:true})// 调用原本的action函数,并记录该action执行的结果const data =awaitaction(context, payload)// 设置loading状态为false
context.commit('setLoading',{
name: fnName,
isLoading:false})// 返回action的执行结果,这个如果不处理的话会导致原本action返回的数据丢失return data
}}}return newActions
}// 配置vuexexportdefaultcreateStore({// state、mutations和上面相同
actions:createActions({asyncgetList(){awaitaxiosTwo()
console.log('请求完成')}})})
最终版本
这种写法貌似也不错,但是还需要手动配置setLoading以及state,这对于不喜欢看文档的童鞋有些许的不友好,因此我们可以将这个函数进行究极进化,不需要手动配置这两个配置项
// 用于生成带有loading的action以及其他的配置functioncreateVuexConfig(config){// 解构对应的属性,并赋默认值const{ actions ={}, state ={}, mutations ={}}= config
// 合并并修改state
config.state = Object.assign(state,{ loading:{}})// 合并并修改mutation
config.mutations = Object.assign(mutations,{setLoading(state,{ name, isLoading }){// 保存loading状态到状态(state)中
state.loading[name]= isLoading
}})// 用于记录装修过的actionsconst newActions ={}// 循环所有的actionfor(const fnName in actions){if(Object.hasOwnProperty.call(actions, fnName)){const action = actions[fnName]// 存储新的action
newActions[fnName]=asyncfunction(context, payload){// 在这个新的action中设置loading状态
context.commit('setLoading',{
name: fnName,
isLoading:true})// 调用原本的action函数,并记录该action执行的结果const data =awaitaction(context, payload)// 设置loading状态为false
context.commit('setLoading',{
name: fnName,
isLoading:false})// 返回action的执行结果,这个如果不处理的话会导致原本action返回的数据丢失return data
}}}// 修改actions
config.actions = newActions
// 返回配置项return config
}
使用教程
仅需在配置vuex时使用该函数包裹即可
exportdefaultcreateStore(createVuexConfig({
actions:{asyncgetList(){awaitaxiosTwo()
console.log('请求完成')return'我是dispatch的执行结果'},asyncgetTwoList(){awaitaxiosTwo()awaitaxiosTwo()
console.log('两次请求完成')}}}))
说明
本文原创,转载请注明出处
版权归原作者 啊哈老郭 所有, 如有侵权,请联系我们删除。