实例能访问到$store的原理
大家看代码的几个高亮部分,核心原理就是,应用了Vue.mixin这个Api的功能
// 如果Vue在window上,直接install
if (!Vue && typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export function install (_Vue) {
if (Vue && _Vue === Vue) {
if (__DEV__) {
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
)
}
return
}
Vue = _Vue
// 调用Vue
applyMixin(Vue)
}
export default function (Vue) {
const version = Number(Vue.version.split('.')[0])
if (version >= 2) {
// 把vueInit混入beforeCreate的生命周期,这里的意思就是后面每个Vue的实例创建都会调用vueInit
Vue.mixin({ beforeCreate: vuexInit })
} else {
// override init and inject vuex init procedure
// for 1.x backwards compatibility.
const _init = Vue.prototype._init
Vue.prototype._init = function (options = {}) {
options.init = options.init
? [vuexInit].concat(options.init)
: vuexInit
_init.call(this, options)
}
}
/**
* Vuex init hook, injected into each instances init hooks list.
*/
function vuexInit () {
const options = this.$options
// store injection
if (options.store) {
// 这里就解释了为什么我们通过this.$store能访问到传入到Vue的store
this.$store = typeof options.store === 'function'
? options.store()
: options.store
} else if (options.parent && options.parent.$store) {
this.$store = options.parent.$store
}
}
}
Vuex的数据是怎么响应的
这里为了大家方便理解,我把源码中部分代码删减掉了,只留了一些核心代码
// 这里的state就是我们store中的state
function resetStoreVM (store, state, hot) {
// store中state的数据放在了data中,(这里的data最终也是放入Vue.observable),把state变成一份可观察的数据
const silent = Vue.config.silent
Vue.config.silent = true
store._vm = new Vue({
data: {
?state: state
},
// 这里的的computed实际就是我们的设置的getters
computed: {...getters}
})
Vue.config.silent = silent
}
我认为的:我在没有看源码之前,我自己也想了一下Vuex中的数据是怎么做到数据响应的,我想到的是Vuex的state是经过Vue.observable处理后,数据变成了响应的了。
实际上:那Vuex这里为啥要重新创建一个Vue的实例,把数据放在data上,然后data再经过Vue.observable处理,为啥要绕这么一圈呢,直接用Vue.observable不是更加简洁吗,大家看上边那段源码里有个computed,就是因为要使用vue中的computed这个功能来缓存getter的结果