Vuex
Vuex是一个转为Vue.js程序开发的状态管理模式.用来几种管理所有组件的状态,并以响应的规则保证状态以一种可预测的方式发生变化.
状态管理应用包含三个部分
- state, 驱动应用的数据源
- view, 以声明方式将state映射到视图
- actions, 响应在view上的用户输入导致的状态变化
全局单例模式管理,可以将组建构成一个巨大的’视图’,不管在树的哪个位置,任何组建都能获取状态或者触发行为!
在简单的页面下可以使用event bus($on,$off,$emit)
- 没一个Vuex应用的核心就是store,’store’基本上就是一个容器,包含着应用中的大部state。Vuex和单纯的全局对象有一下两点不同:
- 状态储存响应式
- 不能直接改变store中的state
store 最简单的store实现
|
|
State 单一状态树
Vuex使用单一状态树 – 用一个对象包含了全部的应用层级状态.作为一个(唯一数据源存在)SSOT.
在Vue组件中获得Vuex状态
Vuex 的状态储存是响应式的,从store实例中读取状态最简单的是在计算属性(computed)中直接返回某个状态
每当store.state.count变化的时候,都会重新求取计算属性,并且触发更新相关联的DOM.
注入后能够通过
this.$store
访问到
mapState 辅助函数
当组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余,因此使用mapState()
可以帮助我们生成计算属性
|
|
当映射的计算属性的名称与state的子节点名称相同时,可以给mapState传递一个数组
对象展开运算符
|
|
Getter
有时候我们需要从store中的state中派生出一些状态,例如对列表进行过滤并计数
Vuex 允许在store中定义getters对象
|
|
mapGetters 辅助函数
|
|
Mutations
更改Vuex的sotre中的位移方法是提交matation。每个mutation都有一个字符串的type和一个handler().这个回调函数就是我们实际进行状态修改的地方,并且它会接收state作为第一个参数
|
|
需要在组件中调用相应的type调用store.commit方法:
大多数请概况下payload应该是一个Object,这样可以包含多个字段并且记录mutation会更易读
提交mutation的另一种风格
Mutations需要遵守的Vue的响应规则
- 最好在store中初始化好所有所需属性
- 当需要在对象上添加新属性时,你应该
- 是用
Vue.set(obj,'newProp',12)
- 以新对象替换老对象:
state.obj = {...state.obj,newProp:123}
- 是用
mutations方法名称最好用常量替代
mutations 必须是同步函数
在组件中使用this.$store.commit('xxx')
提交mutation,或者使用mapMutations()
将组件中的methods映射为store.commit调用js
12345678910111213 import { mapMutations } from 'vuex'export default {// ...methods: {...mapMutations(['increment' // 映射 this.increment() 为 this.$store.commit('increment')]),...mapMutations({add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')})}}
Actions
Action类类似于mutation,不同在于:
- Action提交的是mutation,而不是直接变更状态
- Action可以包含任意异步操作
|
|
Action函数接收一个与store对象具有相同方法和属性的context对象。
可以用到结构赋值
通过store.dispatch()
方法触发
|
|
- 可以内嵌异步方法
- Actions同Mutation一样支持payload和对象方式进行发布
- 调用异步API和分发多从mutations
购物车例子
js 12345678910111213141516actions: {checkout ({ commit, state }, products) {// 把当前购物车的物品备份起来const savedCartItems = [...state.cart.added]// 发出结账请求,然后乐观地清空购物车commit(types.CHECKOUT_REQUEST)// 购物 API 接受一个成功回调和一个失败回调shop.buyProducts(products,// 成功操作() => commit(types.CHECKOUT_SUCCESS),// 失败操作() => commit(types.CHECKOUT_FAILURE, savedCartItems))}}
组件中分发Action
在组件中使用this.$store.dispatch('xxx')
分发action,或者使用mapActions()
辅助函数将组件的methods映射为store.dispatch调用
组合Actions
dispatch()
可以处理被触发的action的回调函数返回的Promise,并且store.dispatch()返回的仍旧是Promise
现在你可以:
|
|
在另外一个 action 中也可以:
|
|
最后,如果我们利用 async / await 这个 JavaScript 即将到来的新特性,我们可以像这样组合 action:
假设 getData() 和 getOtherData() 返回的是 Promise
Modules (https://vuex.vuejs.org/zh-cn/modules.html)
项目结构
- 应用层级的状态应该集中到单个store对象中.
- 提交mutation是更改状态的位一方法,并且这个过程是同步的.
- 异步逻辑都应该封装到action里面.
对于大型应用,Vuex相关代码分割到模块中.下面是项目结构示例: