util相关工具方法
- partial方法,返回只保留闭包环境中的参数的函数。
export function partial (fn, arg) {
return function () {
return fn(arg)
}
}
相关参数介绍
- store:指store实例
- state:根模块的state对象(this._modules.root.state)
- hot:布尔值,用于控制热重载
resetStoreVM 解读
resetStoreVM 初始化 store 的 vm,它负责响应性(也将 _wrappedGetters 注册为计算属性)。
function resetStoreVM(store, state, hot) {
// 存储store的vm
const oldVm = store._vm
// 定义实例的getters对象,以便存储getter
store.getters = {}
//重置本地getters缓存
store._makeLocalGettersCache = Object.create(null)
const wrappedGetters = store._wrappedGetters
const computed = {}
// 遍历wrappedGetters
forEachValue(wrappedGetters, (fn, key) => {
// 若是直接使用内联函数会导致保存oldVm的闭包,所以源码中定义了partial函数,
// 用来返回只保留闭包环境中的参数的函数。使用computed,是为利用其惰性缓存机制。
computed[key] = partial(fn, store)
// 将wrappedGetters中的getter函数名定义到store.getters的对象上。
// 这使得我们可以通过属性形式(例如:store.getters.evenOrOdd)进行访问。
Object.defineProperty(store.getters, key, {
get: () => store._vm[key],
enumerable: true
})
})
// 创建Vue实例前,设置Vue.config.silent = true,是为防止用户添加了一些时髦的
// 全局mixins而出现日志与警告。创建完成后,则设置回原来的值。
const silent = Vue.config.silent
Vue.config.silent = true
store._vm = new Vue({
data: {
$$state: state // 使用Vue实例存储状态树
},
// 将定义的computed变量当做vue的computed属性,以实现getter的返回值会根据它的依赖
// 被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
// computed中的属性会被添加到store._vm上,这也是为何在给store.getters对象
// 定义属性时,设置此属性的get函数返回store._vm[key]的原因
computed
})
Vue.config.silent = silent
// 判断是否启用严格模式
if (store.strict) {
enableStrictMode(store)
}
if (oldVm) {
if (hot) {
// 对所有订阅的观察者发送变更,强制getter重新评估,以便进行热重重载。
store._withCommit(() => {
oldVm._data.$$state = null
})
}
// 销毁旧实例
Vue.nextTick(() => oldVm.$destroy())
}
}
关于 enableStrictMode 和 _withCommit 方法的作用,我在上一篇中已有介绍,有疑惑的同学可以去看看。
结束语
resetStoreVM 的源码并不复杂,它主要是初始化store实例的vm。唯一的难点可能是:让 getter 在通过属性访问时作为 Vue 的响应式系统的一部分缓存其中。为此,给出我个人的两点建议:
-
认真阅读vuex官方文档并会使用vuex。
-
阅读Vue中有关computed的源码