Vuex 方便了管理状态,但也使开发流程更加复杂。为了提高开发速度,“让你少按几次键”,Vuex 提供了诸如mapState方法,但其实帮助不大。如果你在 methods 中看到调用了一个陌生的方法,那十有八九是 Vuex 中的 Action 或者 Mutation。

要是你想使用 v-model 绑定 state 中的字段,享受双向绑定的便捷,那在享受之前,你要好好忍受一下折磨,因为要实现这个功能是很麻烦的:在定义了 state 后,还要定义对应的 mutation;导入到组件的 computed 时,不能使用 mapState,还要给导入的 state 设置 setter,在 setter 中 commit mutation。这是至关重要的一步,否则 v-model 不会正常工作,而是会警告你缺少 setter:

Computed property "xxxx" was assigned to but it has no setter

这实在是很麻烦,必须找到更快捷的方法,更愉快地使用 v-model。这里提供一个简单的方法,应该会提高一点点开发速度。

1、定义通用的 mutation

如果给每一个 state 都定义相应的 mutation,那代码就要写到天荒地老。不妨定义一个通用的 mutation,只需传入需要修改的 state 的字段名和新值:

updateState(state, payload){
    state[payload.key] = payload.val;
}

这样就方便多了。至于一些需要特殊处理的 state,再单独给它们定义 mutation。

2、生成带 setter 的 computed

能用程序生成的,怎么能复制粘贴修改呢?computed 是一个对象,咱们就生成一个对象,再用...操作符合并到组件的 computed 中。

首先在你喜欢的地方新建一个 .js 文件。因为提交 mutation 需要用到 store 实例,store 实例又在 Vue 实例上,咱们就从 main.js 或任何你能想到的地方导出 Vue 实例,在刚才新建的 .js 文件中导入:

import vm from '@/main'

接着,定义一个数组,元素是 state 的字段名:

let stateKeys = ['name', 'age', 'sex'];

接着,循环这个数组,生成计算属性:

let _state = {};
stateKeys.map(key =>{
    _state[key] = {
        get(){
            //如果你的state在模块中,记得在`state`后加上.模块名,下同
            return vm.$store.state[key];
        },
        set(val){
            vm.$store.commit('updateState', {
                key,
                val
            });
        }
    }
})

export const state = _state;

之后,在组件中引入刚刚的 state:
import state from '刚刚的js路径和名称'
最后,在组件的 computed 属性中导入 state:

computed: {
    ...state
}

现在,就能在模板中正常使用 state 了:

<input v-model="name">

最后

一个人不喜欢刷碗不一定是个懒人,他可能只是不喜欢干类似的活。程序员一般都不喜欢干复制粘贴这样的重复性工作 :)

End

标签: vue, vuex, v-model