项目使用 vuex 做数据共享和管理。忙于业务开发时,只关注如何使用,却没想过为何使用。 现在有时间做总结了,在此记录一下。
总结共分三篇:基础篇和原理篇、实践篇、思考篇。建议先浏览一下思考篇的几个问题,再回看基础篇。
本文关注问题速览:
- vuex几个基本概念及关系
- store state module
- getter
- commit mutation action
- 为什么有 actions 和 mutations
- vuex 响应式原理
vuex几个基本概念及关系
store state module
state - state 为状态,Vuex 中的 state,可以理解为一个绑定到界面或组件的状态变量。
store - 每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的 状态 (state)。
module - 当 store 过于臃肿时,可以拆分成子模块维护。实践篇有提及稍复杂的拆分方案。
getter
getter - 可以认为是 store 的计算属性(返回值会根据它的依赖进行缓存,当依赖值变化时,才重新计算)
在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount // 属性访问
}
}
commit mutation action
mutation - 改变 state 所有方法( dispatch | commit )中,最终要走的一步
commit - 触发 mutation 的入口,挂载在 store 对象上
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
store.commit('increment')
为什么有 actions 和 mutations
区分 actions 和 mutations 并不是为了解决竞态问题,而是为了能用 devtools 追踪状态变化。
改变 state 状态,只要最后触发 mutation 就行。
附上尤大的解释 www.zhihu.com/question/48…
vuex 响应式原理
参考文档地址 zhuanlan.zhihu.com/p/78981485
其实很简单:创造一个 vue 实例,借助 vue 的 data 响应式能力和 computed 数据监听能力。
- store 上挂载一个vue实例,叫 store._vm。
- state 注入到 _vm.data 中。
- getters 借助 _vm.computed 做数据监听 + defineProperty 访问代理。
附上源码
function resetStoreVM (store, state, hot) {
const oldVm = store._vm
// 设置 getters 属性
store.getters = {}
const wrappedGetters = store._wrappedGetters
const computed = {}
// 遍历 wrappedGetters 属性
forEachValue(wrappedGetters, (fn, key) => {
// 给 computed 对象添加属性
computed[key] = partial(fn, store)
// 重写 get 方法
// store.getters.xx 其实是访问了store._vm[xx],其中添加 computed 属性
Object.defineProperty(store.getters, key, {
get: () => store._vm[key],
enumerable: true // for local getters
})
})
const silent = Vue.config.silent
Vue.config.silent = true
// 创建Vue实例来保存state,同时让state变成响应式
// store._vm._data.$$state = store.state
store._vm = new Vue({
data: {
$$state: state
},
computed
})
Vue.config.silent = silent
// 只能通过commit方式更改状态
if (store.strict) {
enableStrictMode(store)
}
}