vuex 插件原理解析
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态自管理应用包含以下几个部分:
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。
vuex 核心概念:
- state 是状态、数据
- 使用 mutations 函数更改状态
- 使用 actions 做异步处理
- 使用 getters 做进一步 state 处理
- 将 store 分成模块 modules 做模块化管理
一、 实现 Store 类
- 在 外面使用 new Vuex.Store 时会传入一个对象,对象里会有
state、mutations、getters、actions、modules等对象属性; - 在
constructor分别保存传入的这些参数对象,如下所示:
class Store {
constructor(options) {
this._mutations = options.mutations
this._actions = options.actions
this._wrappedGetters = options.getters
this.getters = {}
}
}
- 实现
state的响应式
用 new Vue 的方式实现响应式
class Store {
constructor(options) {
*省略*
this._vm = new _Vue({
data: {
// 用 $$state 声明方式 防止外面用_vm._data直接访问
$$state: options.state,
},
computed
})
}
// 此处用 get 方式返回响应式对象
get state() {
return this._vm._data.$$state
}
}
- 实现
getters响应式
class Store {
constructor(options) {
*省略*
this._wrappedGetters = options.getters
this.getters = {}
const store = this
const computed = {}
// 遍历getters对象下的每一个方法
Object.keys(this._wrappedGetters).forEach(key => {
const fn = store._wrappedGetters[key]
// 把getters下的每一个方法用函数包装一下并返回执行结果赋值给计算属性
computed[key] = function() {
return fn(store.state)
}
// 设置store.getters的key的访问器属性,这样就可以通过$store.getters.aaa访问
// 获取的时store实例上对应的值
Object.defineProperty(store.getters, key, {
get: () => store._vm[key]
})
})
}
}
- 实现
commit方法
commit(type, payload) {
const mutation = this._mutations[type]
if (!mutation || typeof mutation !== 'function') {
return new Error('UnKnown is' + type)
}
mutation(this.state, payload)
}
- 实现
dispatch方法
dispatch(type, payload) {
const action = this._actions[type]
if (!action || typeof action !== 'function') {
return new Error('UnKnown is' + type)
}
action(this, payload)
}
二、 实现 install 函数
- 创建一个当前模块用的
let _Vue对象, 在 install 方法被调用时会传入 Vue 对象 并 赋值给 _Vue; install函数会在外面Vue.use(Vuex)调用执行- 在
install函数里用全局混入函数Vue.mixin,在beforeCreate钩子函数里挂载$store; - 当前Vuex实例会比 Vue实例早执行,所有要在mixin里做个全局混入,等main.js函数里的new Vue 执行完成后才能拿到 new Vuex.Store 的 实例 store,最后挂载到Vue的原型上
Vue.prototype.$store
_Vue, install, $store 的实现:
function install(Vue) {
_Vue = Vue
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
}
}
})
}
三、 最后导出导出 export default { Store,install }