我们先来看看vuex官方给的一个简单示例。
import Vue from 'vue'
import Vuex from 'vuex'
//注册vuex插件
Vue.use(Vuex)
// root state object.
// each Vuex instance is just a single state tree.
//定义state
const state = {
count: 0
}
// mutations are operations that actually mutates the state.
// each mutation handler gets the entire state tree as the
// first argument, followed by additional payload arguments.
// mutations must be synchronous and can be recorded by plugins
// for debugging purposes.
//定义mutations
const mutations = {
increment (state) {
state.count++
},
decrement (state) {
state.count--
}
}
// actions are functions that cause side effects and can involve
// asynchronous operations.
//定义actions
const actions = {
increment: ({ commit }) => commit('increment'),
decrement: ({ commit }) => commit('decrement'),
incrementIfOdd ({ commit, state }) {
if ((state.count + 1) % 2 === 0) {
commit('increment')
}
},
incrementAsync ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('increment')
resolve()
}, 1000)
})
}
}
// getters are functions
//定义getters
const getters = {
evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
}
// A Vuex instance is created by combining the state, mutations, actions,
// and getters.
//导出vuex实例
export default new Vuex.Store({
state,
getters,
actions,
mutations
})
首先注册vuex插件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
然后分别定义state、mutations、actions、getters,并导出
最后将vuex对象实例挂载到vue的每一个实例上去
new Vue({
el: '#root',
router,
store,
render: h => h(App)
})
vuex作为vue的一个插件,在使用插件vue.use(vuex)时,会通过vuex对象中的install方法将vuex载入,现在我们来看看install方法的实现。
install方法在store.js文件中
export function install (_Vue) {
//这里使用全局变量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)函数上
我们来看看applyMixin函数,在mixin.js文件中
export default function (Vue) {
const version = Number(Vue.version.split('.')[0])
if (version >= 2) {
//在2.x.x以上版本,直接使用hook的形式进行注入
Vue.mixin({ beforeCreate: vuexInit })
} else {
// override init and inject vuex init procedure
// for 1.x backwards compatibility.
//在2.x.x一下版本,使用封装并替换Vue对象原型的_init方法,实现注入
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属性上
this.$store = typeof options.store === 'function'
? options.store()
: options.store
} else if (options.parent && options.parent.$store) {
//子组件从其父组件引用$store属性,层层嵌套进行设置
this.$store = options.parent.$store
}
}
}
在安装注入函数时会判断vue的版本,2.x.x以上版本,使用 hook 的形式进行注入,而低于2.x.时使用封装并替换Vue对象原型的_init方法,实现注入。
注入的函数实现的功能其实就是当vuex设置到vue对象的$store属性上,便于在任意组件中执行 this.$store 都能找到装载的那个store对象。 这里它会判断设置的是根组件还是非根组件,根组件时直接设置到this对象的$store属性上,子组件则从其父组件引用$store属性,层层嵌套进行设置。
到此,vuex的安装工作就已经完成了。
这一节我们只是简单的看了一下vuex的使用方式,顺便解析了下vuex安装注入到vue实例上的过程。下节我们将进入vuex的核心内容。