先看 vuex 源码目录
源码都在 src
目录下,入口文件为 index.js
(或 index.esm.js
),当用 import Vuex from 'vuex'
引入 vuex
时,入口就是 index.esm.js
(esm: es6 module),看看里面
import { Store, install } from './store'
import { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from './helpers'
export default {
Store,
install,
version: '__VERSION__',
mapState,
mapMutations,
mapGetters,
mapActions,
createNamespacedHelpers
}
export {
Store,
install,
mapState,
mapMutations,
mapGetters,
mapActions,
createNamespacedHelpers
}
首先就是引入 Store
和 install
,先看看 install
方法
export function install (_Vue) {
// Vue 已经存在并且相等,说明已经 Vuex 已经 install 过
if (Vue && _Vue === Vue) {
// 非生产环境报错,vuex已经安装,代码继续执行
if (process.env.NODE_ENV !== 'production') {
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
)
}
return
}
Vue = _Vue
applyMixin(Vue)
}
上述代码逻辑很简单,执行 Vuex.install
时传入 Vue
构造函数,最后再执行 applyMixin(Vue)
但是,通常情况下,我们引入 Vuex
之后,都是执行 Vue.use(vuex)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
看看 vue
源码
// src/core/global-api/use.js
/* @flow */
import { toArray } from '../util/index'
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) {
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters
const args = toArray(arguments, 1)
args.unshift(this)
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
installedPlugins.push(plugin)
return this
}
}
如果传进来的 plugin
有 install
方法,就执行 install
方法,当然我们也可以直击直接 install
方法,效果是一样的
import Vue from 'vue'
import Vuex from 'vuex'
Vuex.install(Vue)
再来看看 applyMixin
方法,这个方法在 mixin.js
中
// vuex/src/minx.js
export default function (Vue) {
const version = Number(Vue.version.split('.')[0]) // 2
if (version >= 2) {
// 全局混入了一个 beforeCreate 钩子函数
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 注入
// 使得每个Vue实例下 都有 $store 这个对象(Store 实例,包含一系列方法和属性),且是同一个对象。
// 先是判断 options.store 也就是 这个
// 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
}
}
}
看看 Vue
的源码中 Vue.mixin
方法
// src/core/global-api/mixin.js
/* @flow */
import { mergeOptions } from '../util/index'
export function initMixin (Vue: GlobalAPI) {
Vue.mixin = function (mixin: Object) {
this.options = mergeOptions(this.options, mixin)
return this
}
}
其实就是全局混入了一个 beforeCreate 钩子函数,打印 Vue 实例看看
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。