全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。 不推荐在应用代码中使用。
在 vue 的 initGlobalAPI 入口方法中调用了 initMixin$1(Vue) 方法:
function initMixin$1 (Vue) { Vue.mixin = function (mixin) { this.options = mergeOptions(this.options, mixin); return this }; }
Vuex 注入 Vue 生命周期的过程大概就是这样,如果你感兴趣的话,你可以直接看看 Vuex 的源码,接下来我们说说 Store。
Store
上面我们讲到了 vuexInit 会从 options 中获取 Store。所以接下来会讲到 Store 是怎么来的呢?
我们使用 Vuex 的时候都会定义一个和下面类似的 Store 实例。
import Vue from 'vue' import Vuex from 'vuex' import mutations from './mutations' Vue.use(Vuex) const state = { showState: 0, } export default new Vuex.Store({ strict: true, state, getters, })
不要在发布环境下启用严格模式。严格模式会深度监测状态树来检测不合规的状态变更 —— 请确保在发布环境下关闭严格模式,以避免性能损失。
state 的响应式
你是否关心 state 是如何能够响应式呢?这个主要是通过 Store 的构造函数中调用的 resetStoreVM(this, state) 方法来实现的。
这个方法主要是重置一个私有的 _vm(一个 Vue 的实例) 对象。这个 _vm 对象会保留我们的 state 树,以及用计算属性的方式存储了 store 的 getters。现在具体看看它的实现过程。
/* 使用 Vue 内部的响应式注册 state */ function resetStoreVM (store, state, hot) { /* 存放之前的vm对象 */ const oldVm = store._vm store.getters = {} const wrappedGetters = store._wrappedGetters const computed = {} /* 通过 Object.defineProperty 方法为 store.getters 定义了 get 方法。当在组件中调用 this.$store.getters.xxx 这个方法的时候,会访问 store._vm[xxx]*/ forEachValue(wrappedGetters, (fn, key) => { computed[key] = partial(fn, store) Object.defineProperty(store.getters, key, { get: () => store._vm[key], enumerable: true // for local getters }) }) const silent = Vue.config.silent /* 设置 silent 为 true 的目的是为了取消 _vm 的所有日志和警告 */ Vue.config.silent = true /* 这里new了一个Vue对象,运用Vue内部的响应式实现注册state以及computed*/ store._vm = new Vue({ data: { $$state: state }, computed }) Vue.config.silent = silent /* 使能严格模式,Vuex 中对 state 的修改只能在 mutation 的回调函数里 */ if (store.strict) { enableStrictMode(store) } if (oldVm) { /* 解除旧 vm 的 state 的引用,并销毁这个旧的 _vm 对象 */ if (hot) { store._withCommit(() => { oldVm._data.$$state = null }) } Vue.nextTick(() => oldVm.$destroy()) } }
state 的响应式大概就是这样实现的,也就是初始化 resetStoreVM 方法的过程。
看看 Store 的 commit 方法
我们知道 commit 方法是用来触发 mutation 的。
commit (_type, _payload, _options) { /* unifyObjectStyle 方法校参 */ const { type, payload, options } = unifyObjectStyle(_type, _payload, _options) const mutation = { type, payload } /* 找到相应的 mutation 方法 */ const entry = this._mutations[type] if (!entry) { if (process.env.NODE_ENV !== 'production') { console.error(`[vuex] unknown mutation type: ${type}`) } return } /* 执行 mutation 中的方法 */ this._withCommit(() => { entry.forEach(function commitIterator (handler) { handler(payload) }) }) /* 通知所有订阅者,传入当前的 mutation 对象和当前的 state */ this._subscribers.forEach(sub => sub(mutation, this.state)) if ( process.env.NODE_ENV !== 'production' && options && options.silent ) { console.warn( `[vuex] mutation type: ${type}. Silent option has been removed. ` + 'Use the filter functionality in the vue-devtools' ) } }
该方法先进行参数风格校验,然后利用 _withCommit 方法执行本次批量触发 mutation 处理函数。执行完成后,通知所有 _subscribers (订阅函数)本次操作的 mutation 对象以及当前的 state 状态。