我们先把vuex安装到vue中
import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './modules/moduleA'
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
const store = new Vuex.Store({
modules: {
moduleA,
},
strict: debug,
})
export default store
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App)
}).$mount("#app")
上面我们可以看到我们在options中加入了store属性
接下来我们看vuex的源码如何工作的?
.vuex安装的源码显示?
.vuex安装后我们可以看到vuex的初始化vuexInit函数运行了3次,都起什么作用?(一次是vue的入口地址显示, 二次是vuex自身源码需要实例化vue)
>目的:主要是为了说明vuex自身源码需要实例化vue 2次,在实际项目中总数会大于3次
一、vuex安装的源码显示?
我们知道Vue.use(Vuex)的源码原理,找到vuex的install函数
function install (_Vue) {
if (Vue && _Vue === Vue) {
if ((process.env.NODE_ENV !== 'production')) {
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
);
}
return
}
Vue = _Vue;
applyMixin(Vue);
}
接着查看 applyMixin(Vue)函数
.我们用的是版本是2.6.11,所以只需要了解version >= 2这个分支即可
这里我们看到会给各个vue实例写入{ beforeCreate: vuexInit }函数
function applyMixin (Vue) {
var version = Number(Vue.version.split('.')[0]);
if (version >= 2) {
Vue.mixin({ beforeCreate: vuexInit });
} else {
......
};
}
/**
* Vuex init hook, injected into each instances init hooks list.
*/
function vuexInit () {
var options = this.$options;
// store injection
if (options.store) {
this.$store = typeof options.store === 'function'
? options.store()
: options.store;
} else if (options.parent && options.parent.$store) {
this.$store = options.parent.$store;
}
}
}
接着从chrome的调试工具中我们也可以看到,已经写入vue的$options的beforeCreate中.
vuex安装后我们可以看到vuex的初始化vuexInit函数运行了3次,都起什么作用?
我们已经知道vuexInit写入了vue的$options的beforeCreate,它运行了3次,也就说明有3个vue的实例生成
1.vue的entry的main.js
new Vue({
store,
render: h => h(App)
}).$mount("#app")
作用:初始化vue实例并渲染显示到界面
2.在vuex的源码中我们可以看到
var Store = function Store (options) {
......
this._watcherVM = new Vue();
......
}
作用:我们可以看到Store.prototype.watch实际上运行的就是Vue原型链上的函数$watch
Store.prototype.watch = function watch (getter, cb, options) {
var this$1 = this;
if ((process.env.NODE_ENV !== 'production')) {
assert(typeof getter === 'function', "store.watch only accepts a function.");
}
return this._watcherVM.$watch(function () { return getter(this$1.state, this$1.getters); }, cb, options)
};
3.在vuex的源码中我们可以看到
function resetStoreVM (store, state, hot) {
var oldVm = store._vm;
......
store._vm = new Vue({
data: {
$$state: state
},
computed: computed
});
......
if (oldVm) {
if (hot) {
// dispatch changes in all subscribed watchers
// to force getter re-evaluation for hot reloading.
store._withCommit(function () {
oldVm._data.$$state = null;
});
}
Vue.nextTick(function () { return oldVm.$destroy(); });
}
}
作用:这里我们看到这个vue实例的data对象是为了对比变化实例热更新