VUEX的使用总结
1、为什么要使用vuex
官方说法:当多个组件共享数据状态时,单向数据流非常容易被影响甚至破坏,因此需要创建一个全局单例模式的管理方式,用以解决多个视图依赖于统一状态,以及来自不同视图的行为需要变更为同一状态等问题。
真实体验:因为父组件与子组件的交互规则,父组件想调用子组件中定义的方法并修改子组件的数据非常麻烦,所以当父子组件交互频繁的时候,非常需要一种机制来处理二者的关系。
2、开始
1)在自己的项目中创建一个store文件夹,如图:
modules文件夹用来放置store分割成的各个模块,每个模块都有单独的state、mutation、action、getter等;mutation-types.js是一个执行动作类型的集合,里面变量一般要大写;index.js则是将各个module中的store整理到一起:
1 |
|
这种方式,向外暴露一个Vuex.Store实例。
知识点1:strict代表是否设置为严格模式,在严格模式下,如果state发生变化不是有mutation函数引起的,将会抛出错误,用以保证所有状态都能被调试工具跟踪到。
知识点2:通过module维护各个store,优点是当项目比较大型时能够非常清晰的管理和维护数据。
2)我们在创建vue项目时,src文件夹下有一个main.js,在这个文件中引入./store,在实例化vue对象时注入store对象:
1 |
|
以上的引用方式,保证了我们在各个子组件中能通过this.$store的方式访问到状态树中的数据。
3、详解各核心概念
1)state
官方名称叫”单一状态树”,它作为一个”唯一数据源”存在。这意味着,每个应用将仅仅包含一个store实例。
vuex的状态存储有以下几个特点:
a.响应式存储:也就是说,当state中的某个数据发生变化时,我们通过计算属性能够轻易的获取其变化后的值。
b.要尽可能的在state中声明我们需要的所有变量,方便后面mutation访问和修改。
2)mapState
由于在组件中我们需要频繁的声明和计算state重的变量,那么就会产生一下写法:
1 |
|
这样代码即复杂又冗余,以下方法完全可以将其替代:
1 |
|
mapState和对象展开运算符结合的写法:
1 |
|
上述代码这种写法,将state状态和其他的计算变量集合到一起,并将其最终传给computed,通过this.localComputed和this.xxx访问。
3)getter
在真正的项目开发中,经常会遇到,vuex中的变量要进行一些计算然后复用到多个地方,这时,getter就派上了用场:
1 |
|
上述代码在store中定义了getter,就像computed一样,getter定义的值会被缓存起来,当它依赖的数据发生变化时,才会随之更新。
在组件中通过this.$store.getters.xxx访问。
4)mapGetters
与 mapState() 类似 mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
1 |
|
5)mutation
以上state和getter都是用来获取store的数据状态的,而mutaion是可以修改store中的数据的。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。回调函数就是真正要去修改store数据的地方,并接受state作为第一个参数。
提交 mutation 需要用到 store 的 store.commit() 方法。
注意:mutation函数必须是同步的,原因是是我们不知道异步的毁掉函数什么时候被调用,对修改store中数据会造成很严重的影响。
1 |
|
也可以在组件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。
1 |
|
6)mapMutation
同 mapState 和 mapGetters 一样,mapMutations 可以节约代码,使代码更加简洁,它将会在组件的 methods 属性中完成映射:
1 |
|
7)action
action跟mutation很类似,但有两点不同之处:
第一,action支持异步。
第二,action只能提交mutation,而不能直接操作state。
action 函数接受一个与 store 实例具有相同方法和属性的 context 对象(之所以这样讲,是因为modules的缘故),因此你可以调用 context.commit 提交一个 mutation:
1 |
|
在action中可以提交多次 mutation。
在子组件中,我们一般采用store.dispatch(‘xxx’)的方式触发action:
1 |
|
8)mapAction
与 mapMutation 类似,用于将 action 映射到组件中:
1 |
|
action 可以组合使用,也就是在一个 action 中调用另外一个 action,在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。
参考文献: