vuex

vuex 是什么

vuex 是专门为 vue 应用程序设计的状态管理工具。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

设计思想

vuex 的设计思想借鉴了 Flux、Redux,将数据存储在全局的 store,再将 store 挂载到每个 vue 实例组件中,利用 vue 的细粒度数据响应机制来进行高效的状态更新

原理解析

主要理解两个问题

  • vuex 的 store 是如何挂载注入到组件中呢?
  • vuex 的 state 和 getters 是如何映射到各个组件实例中响应式更新状态呢?

vuex 的 store 如何挂载注入到组件中

首先安装 vuex

import Vuex from 'vuex';
Vue.use(Vuex);

由于 vue 的插件机制,在使用Vue.use(vuex)时,会调用 vuex 的 install 方法来装载 vuex,install 方法如下

export function install(_Vue) {
    if (Vue && _Vue === Vue) {
        if (process.env.NODE_NEV !== 'production') {
            console.error(
                '[vuex] already install. Vue.use(Vuex) should be called only once'
            );
        }
        return;
    }
    Vue = _Vue;
    applyMixin(Vue);
}

applyMixin 方法使用了 vue 的混入机制,在 vue 的声明周期 beforeCreate 钩子函数前混入 vuexInit 方法,核心代码如下

Vue.mixin({ beforeCreate: vuexInit });
function vuexInit() {
    const options = this.$options;
    if (options.store) {
        this.$store =
            typeof options.store === 'function'
                ? options.store()
                : options.store;
    } else if (options.parent && options.parent.$store) {
        this.$store = optioins.parent.$store;
    }
}

小结:通过分析源码得知,vuex 利用了 vue 的 mixin 混入机制,在 beforeCreate 钩子前混入 vuexInit 方法,vuexInit 方法实现了 store 注入 vue 组件实例,并且注册了 vuex store 的引用属性$store,store 注入 过程如下图

vuex 的 state 和 getters 是如何映射到各个组件实例中响应式更新状态

store 实现的源码在 src/store.js

核心方法 resetStoreVM 如下

function resetStoreVM(store, state, hot) {
    const oldVm = store._vm;
    store.getters = {};
    const wrappedGetters = store._wrappedGetters;
    const computed = {};
    forEachValue(wrappedGetters, (fn, key) => {
        // 给 computed 对象添加属性
        computed[key] = partial(fn, store);
        // 重写 get 方法,store.getters.xx 其实是访问了store._vm[xx],其中添加 computed 属性
        Object.defineProperty(store.getters, key, {
            get: () => store._vm[key],
            enumerable: true,
        });
    });

    const silent = Vue.config.silent;
    Vue.config.silent = true;
    // 创建 Vue 实例来保存 state,同时让 state 变成响应式
    // 这里代码才是核心,其实就是把 store 变成一个隐藏组件的 data
    store._vm = new Vue({
        data: {
            $$state: state,
        },
        computed,
    });
    Vue.config.silent = silent;
    // 只能通过 commit 方式更改状态
    if (store.strict) {
        enableStrictMode(store);
    }
}

从上面源码可以看出 vuex 的 state 状态是响应式,是借助 vue 的 data 生成的,将 store 存入 一个隐藏的 vue 实例组件的 data 中;vuex 的 getters 则是借助 vue 的计算属性 computed 实现数据监听

computed 计算属性监听 data 数据变更主要经历以下几个过程

总结

vuex 是通过全局注入 store 对象,来实现组件间的状态共享。在大型复杂的项目中(多级组件嵌套),需要实现一个组件更改某个数据,多个组件自动获取更改后的数据进行业务逻辑处理,这时候使用 vuex 比较合适。假如只是多个组件间传递数据,使用 vuex 未免有点大材小用,其实只用使用组件间常用的通信方法即可。

一句话结束 vuex 工作原理:vuex 中的 store 本质就是没有 template 的隐藏着的 vue 组件;

Last Updated:
Contributors: af