使用的源码版本为3.5.1
定义
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
使用场景
它的优势用于解决下面两个问题:
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
解决方式是:
- 全局单例集中管理
- 数据单向流动
源码架构
vuex源码架构核心点两个:
- 观察者模式
- 把state中的状态处理成响应式的
观察者模式
我们定义的Action和Mutation都是具体的事件,会被vuex搜集保存起来
function installModule (store, rootState, path, module, hot) {
module.forEachMutation((mutation, key) => {
const namespacedType = namespace + key
registerMutation(store, namespacedType, mutation, local)
})
module.forEachAction((action, key) => {
const type = action.root ? key : namespace + key
const handler = action.handler || action
registerAction(store, type, handler, local)
})
}
function registerMutation (store, type, handler, local) {
const entry = store._mutations[type] || (store._mutations[type] = [])
entry.push(function wrappedMutationHandler (payload) {
handler.call(store, local.state, payload)
})
}
function registerAction (store, type, handler, local) {
const entry = store._actions[type] || (store._actions[type] = [])
entry.push(function wrappedActionHandler (payload) {
let res = handler.call(store, {
dispatch: local.dispatch,
commit: local.commit,
getters: local.getters,
state: local.state,
rootGetters: store.getters,
rootState: store.state
}, payload)
if (!isPromise(res)) {
res = Promise.resolve(res)
}
if (store._devtoolHook) {
return res.catch(err => {
store._devtoolHook.emit('vuex:error', err)
throw err
})
} else {
return res
}
})
}
dispatch和commit的作用是发布事件
// 只保留核心代码
dispatch (_type, _payload) {
// check object-style dispatch
const {
type,
payload
} = unifyObjectStyle(_type, _payload)
const action = { type, payload }
const entry = this._actions[type]
const result = entry.length > 1
? Promise.all(entry.map(handler => handler(payload)))
: entry[0](payload)
// 只保留核心代码
commit (_type, _payload, _options) {
// check object-style commit
const {
type,
payload,
options
} = unifyObjectStyle(_type, _payload, _options)
const mutation = { type, payload }
const entry = this._mutations[type]
this._withCommit(() => {
entry.forEach(function commitIterator (handler) {
handler(payload)
})
})
}
dispach发布事件,遍历找到对应的action处理,处理异步操作完成之后调用commit提交事件,遍历找到对应的mutation去处理(主要是修改state中数据状态),这样就完成了整个流程
响应式原理
在store的构造器中会调用resetStoreVM
// 只保留核心代码
function resetStoreVM (store, state, hot) {
store._vm = new Vue({
data: {
$$state: state
},
computed
})
}
核心是创建一个vue实例,利用vue响应式原理把state的中的数据处理成响应式的。
vue响应式的原理可以看我的这篇文章:从源码的角度分析Vue视图更新和nexttick机制
参考:
https://www.jianshu.com/p/d95a7b8afa06
https://vuex.vuejs.org/zh/guide/actions.html
https://tech.meituan.com/2017/04/27/vuex-code-analysis.html