Skip to content
On this page

Vuex 的实现原理

先来看下是怎么使用的:

简单实现,只为看清本质:

实现一个插件:声明 Store 类,挂载 $store Store 具体实现:

  • 创建响应式的 state,保存 mutations、actions 和 getters
  • 实现 commit 根据用户传入 type 执行对应 mutation
  • 实现 dispatch 根据用户传入 type 执行对应 action
  • 实现 getters
js
// 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
        const getters = options.getters || {};
        this.getters = {};
        Object.keys(getters).forEach(getterName => {
            Object.defineProperty(this.getters, getterName, {
                get: () => {
                    return getters[getterName](this.state);
                }
            })
        })
        // mutation
        const mutations = options.mutations || {};
        this.mutations = {};
        Object.keys(mutations).forEach(mutationName => {
            this.mutations[mutationName] = payload => {
                mutations[mutationName](this.state, payload);
            }
        })
        // action
        const 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
}