vue项目中或多或少都会出现vuex的身影,如何正确有效的使用vuex,是一件很值得探讨的问题。
什么时候使用vuex?
这是我们首先要想明白的问题?有些同学看项目里有别人在用,自己也跟着用?结果导致仓库庞大,难以维护。
引用 Redux 的作者 Dan Abramov 的话说就是:
Flux 架构就像眼镜:您自会知道什么时候需要它。
说了什么,又好像什么也没说。
其实这句话很有道理。拿我们的项目举例,有一个页面,三个组件共同关心一个数据状态。重构之前的做法是子组件通过事件传递给父组件,父组件再下发给其他的子组件。但是这种方法过于繁琐,尤其是子组件下又有子组件的情况,实在是难以维护。于是在想有没有一种可以集中管理这个数据的全局变量,自然而然地就想到了vuex。
当你的项目遇到多组件共享数据状态的时候,就可以考虑用vuex来维护,尤其是组件之间关系比较远的情况。对于简单的父子组件,兄弟组件,我觉得用事件总线或者自定义事件解决更方便且易维护。
actions 和 mutations的区别
这个问题我在知乎找到了答案,这是尤雨溪大佬的回答(部分省略)
区分 actions 和 mutations 并不是为了解决竞态问题,而是为了能用 devtools 追踪状态变化。这样 devtools 就可以打个 snapshot 存下来,然后就可以随便 time-travel 了。如果你开着 devtool 调用一个异步的 action,你可以清楚地看到它所调用的 mutation 是何时被记录下来的,并且可以立刻查看它们对应的状态。
简而言之,对于 mutation 而言,方法体里是可以进行异步操作的,但是这样无法很好的用devtools跟踪调试,使用actions会更加友好。
还有一方面是,大家都按照约定去执行,也相对来说比较好维护。
严格模式的原理
其实很简单,vuex会维护一个标识符来表示是否调用了commit
,假如数据修改了但是没有通过commit
修改,则会抛出异常。
严格模式会有性能消耗,所以我们只需要在开发环境打开即可,在生产环境要关闭掉
模块
把所有的state
都维护在全局命名空间下会导致state
过于庞大,难以维护,这时候我们就需要使用模块
局部命名空间
在定义模块的时候,模块内部使用的state
都是局部的state
.但是在外部想引用模块内的state
需要加上命名空间.
像这样
$store.state.moduleA.test
但是mutations
,actions
,getters
是全局注册的,我们只需要直接使用即可
$store.commit('ModuleAMutation')
开启命名空间
如果我们希望mutations
,actions
,getters
,也注册在局部命名空间下,就需要增加配置
export default {
namespaced:true
}
这样我们就可以这样使用
$store.commit('moduleA/mutation')
$store.dispatch('moduleA/action')
$store.getters['moduleA/test']
辅助函数
当然对于辅助函数来讲,我们也可以指定命名空间
mapState('moduleA',['stateA'])
mapGetters('moduleA',['getterA'])
mapMutations('moduleA',['mutation'])
mapActions('moduleA',['action'])