看了
Vuex
源码文件,发现确实很多,我这里就讲我们最常用的部分功能的源码吧
其实使用过 Vuex 的同学都知道,我们在页面或者组件中都是通过
this.$store.xxx
来调用的,那么其实,我们只要把你所创建的store
对象赋值给页面或者组件中的$store
变量即可
Vuex
的原理通俗讲就是:利用了全局混入Mixin
,将你所创建的store
对象,混入到每一个Vue实例
中,那么全局混入
是什么呢?举个例子:
import Vue from 'vue' // 全局混入 Vue.mixin({ created () { console.log('我是孙悟空') } }) // 之后创建的Vue实例,都会输出'我是孙悟空' const a = new Vue({ // 这里什么都没有,却能实现输出'我是孙悟空' }) // => "我是孙悟空" const b = new Vue({ // 这里什么都没有,却能实现输出'我是孙悟空' }) // => "我是孙悟空"
上面例子看懂的人,就知道了,同理,把
console.log('我是林三心')
这段代码换成一段能做这件事的代码:把store赋值给实例的$store
属性,就实现了:
目录
// vuex.js let Vue; // install方法设置,是因为Vue.use(xxx)会执行xxx的install方法 const install = (v) => { // 参数v负责接收vue实例 Vue = v; // 全局混入 Vue.mixin({ beforeCreate() { if (this.$options && this.$options.store) { // 根页面,直接将身上的store赋值给自己的$store, 这也解释了为什么使用vuex要先把store放到入口文件main.js里的根Vue实例里 this.$store = this.$options.store; } else { // 除了根页面以外,将上级的$store赋值给自己的$store this.$store = this.$parent && this.$parent.$store; } }, }) } // 创建类Store class Store { constructor(options) { // options接收传入的store对象 this.vm = new Vue({ // 确保state是响应式 data: { state: options.state } }); // getter let getters = options.getters || {}; this.getters = {}; console.log(Object.keys(this.getters)) Object.keys(getters).forEach(getterName => { Object.defineProperty(this.getters, getterName, { get: () => { return getters[getterName](this.state); } }) }) // mutation let mutations = options.mutations || {}; this.mutations = {}; Object.keys(mutations).forEach(mutationName => { this.mutations[mutationName] = payload => { mutations[mutationName](this.state, payload); } }) // action let actions = options.actions || {}; this.actions = {}; Object.keys(actions).forEach(actionName => { this.actions[actionName] = payload => { actions[actionName](this.state, payload); } }) } // 获取state时,直接返回 get state() { return this.vm.state; } // commit方法,执行mutations的'name'方法 commit(name, payload) { this.mutations[name](payload); } // dispatch方法,执行actions的'name'方法 dispatch(name, payload) { this.actions[name](payload); } } // 把install方法和类Store暴露出去 export default { install, Store }
// index.js import Vue from 'vue'; import vuex from './vuex'; // 引入vuex.js暴露出来的对象 Vue.use(vuex); // 会执行vuex对象里的install方法,也就是全局混入mixin // 实例一个Store类,并暴露出去 export default new vuex.Store({ state: { num: 1 }, getters: { getNum(state) { return state.num * 2; } }, mutations: { in (state, payload) { state.num += payload; }, de(state, payload) { state.num -= payload; } }, actions: { in (state, payload) { setTimeout(() => { state.num += payload; }, 2000) } } })
// main.js import Vue from 'vue'; import App from './App.vue' import store from './store/index'; // 引入刚刚的index.js new Vue({ store, // 把store挂在根实例上 el: '#app', components: { App }, template: '<App/>', })
至此,简单实现了vuex的state,mutations,getter,actions。以后有机会会专门写一篇实现mudule的
vue是不提倡全局混入mixin的,甚至连mixin都不倡导使用,别乱用哦!
参考文章