vuex作为Vue的官方状态管理库,遵循以下原则
- 状态只读
- 多个视图依赖同一个状态,共同维护一颗状态树
- 相同状态,渲染出相同的视图
下面是官方图解释:
初始化:
import Vuex from 'vuex'
Vue.use(Vuex);
// 建立一个store
const store = new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment: function(state) {
state.count++;
}
}
})
// 注入store
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
// 访问state
<div>{{this.$store.state.count}}</div>
// 触发commit
this.$store.commit('increment')
// 也可以传递参数payload
this.$store.commit('increment', n)
vuex里面的getter属性,Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
getters: {
doneTools: state => state.todos.filter(todo => todo.done),
},
// 访问
store.getters.doneTodos
Mutation(类似redux里面的reducer)
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
一条重要的原则就是要记住 mutation 必须是同步函数,现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。
actions(类似redux里面的middleware)
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
actions: {
incrementSync: function({commit}) {
setTimeout(() => {
commit('increment');
}, 1000);
}
},
this.$store.dispatch('incrementSync')
Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
const store = new Vuex.Store({
modules: {
articalDetailMoudule,
}
})
对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState