Vuex(三)

451 阅读3分钟

Vuex(一)
Vuex(二)
Vuex3个类思维导图

Vue中的三个类:Stroe,Module,ModuleCollection

Module类

Module类用来操作基础数据的存储,与读取。
Module 值描述
参数值
runtime 布尔值,false 状态下该Module 不可被删除,true 状态下可以被删除
_children 装的子项module
_rawModule state,actions,mumations...等参数
state 状态数据
namespaced 命名空间规则;布尔值
函数
addChild 添加_children
removeChild 删除_children
getChild 获取 _children
update 更新字段内容,有 namespaced,actions,mutations,getters
forEachChild 遍历自身_children,函数回调
forEachGetter 遍历自身getters,函数回调
forEachAction 遍历自身actions,函数回调
forEachMutation 遍历自身mutations,函数回调
    var prototypeAccessors = {namespaced: {configurable: true}};

    prototypeAccessors.namespaced.get = function () {
        return !!this._rawModule.namespaced
    };

    Module.prototype.addChild = function addChild(key, module) {
        this._children[key] = module;
    };

    Module.prototype.removeChild = function removeChild(key) {
        delete this._children[key];
    };

    Module.prototype.getChild = function getChild(key) {
        return this._children[key]
    };
    // 更新module 内容
    Module.prototype.update = function update(rawModule) {
        this._rawModule.namespaced = rawModule.namespaced;
        if (rawModule.actions) {
            this._rawModule.actions = rawModule.actions;
        }
        if (rawModule.mutations) {
            this._rawModule.mutations = rawModule.mutations;
        }
        if (rawModule.getters) {
            this._rawModule.getters = rawModule.getters;
        }
    };
    // 遍历子项 函数回调
    Module.prototype.forEachChild = function forEachChild(fn) {
        forEachValue(this._children, fn);
    };
    // 遍历 getters 回调函数绑定
    Module.prototype.forEachGetter = function forEachGetter(fn) {
        if (this._rawModule.getters) {
            forEachValue(this._rawModule.getters, fn);
        }
    };
     // 遍历actions 函数回调绑定
    Module.prototype.forEachAction = function forEachAction(fn) {
        if (this._rawModule.actions) {
            forEachValue(this._rawModule.actions, fn);
        }
    };
    // 遍历mutations 函数回调绑定
    Module.prototype.forEachMutation = function forEachMutation(fn) {
        if (this._rawModule.mutations) {
            forEachValue(this._rawModule.mutations, fn);
        }
    };

    Object.defineProperties(Module.prototype, prototypeAccessors);
        // 遍历对象返回键与值
       function forEachValue(obj, fn) {
        Object.keys(obj).forEach(function (key) {
            return fn(obj[key], key);
        });
    }

ModuleCollection类

ModuleCollection类控制着Module的修改,一个根节点(root)。
ModuleCollection 值描述
参数值
root 根节点,对应的是Module对象
函数
get 根据 传入一个 数组,默认从自身root开始查找 子项Module
getNameSpace 传入一个数组,从root中获取_children ,根据_children.namespaced 来判断 返回 namespace + (module.namespaced ? key + '/' : '')
update 调用Module.update 更新内容
register 初始化内容,创建Module对象,递归Module,添加_children
unregister 根据runtime 来判断是否 删除_chidlren
    Object.defineProperties(Module.prototype, prototypeAccessors);
    var ModuleCollection = function ModuleCollection(rawRootModule) {
        // register root module (Vuex.Store options)
        this.register([], rawRootModule, false);
    };
    // path 是一个数组,内容字符串,就是modules中的键名
    // 查找子项 module, 数组为空,默认返回根节点
    ModuleCollection.prototype.get = function get(path) {
        return path.reduce(function (module, key) {
            return module.getChild(key)
        }, this.root)
    };
    // namespace 名称的拼凑
    ModuleCollection.prototype.getNamespace = function getNamespace(path) {
        var module = this.root;
        return path.reduce(function (namespace, key) {
            // 获取module
            module = module.getChild(key);
            // 根据 namespaced 状态来 加前缀
            return namespace + (module.namespaced ? key + '/' : '')
        }, '')
    };
    //  修改Modules 
    ModuleCollection.prototype.update = function update$1(rawRootModule) {
        update([], this.root, rawRootModule);
    };
    // 
    function update(path, targetModule, newModule) {
        {
            assertRawModule(path, newModule);
        }
        // update target module
        targetModule.update(newModule);
        // update nested modules
        if (newModule.modules) {
            for (var key in newModule.modules) {
                if (!targetModule.getChild(key)) {
                    {
                        console.warn(
                            "[vuex] trying to add a new module '" + key + "' on hot reloading, " +
                            'manual reload is needed'
                        );
                    }
                    return
                }
                // 递归更新
                update(
                    path.concat(key),
                    targetModule.getChild(key),
                    newModule.modules[key]
                );
            }
        }
    }
    // 初始换内容
    ModuleCollection.prototype.register = function register(path, rawModule, runtime) {
        // rawModule -> options
        var this$1 = this;
        if (runtime === void 0) runtime = true;

        // 验证 getter,actions,mutations
        // 其中 actions 中 可以为 函数,对象,但是对象中必须有 handler 函数
        {
            assertRawModule(path, rawModule);
        }
        // 初始化Module
        // 初始化 state
        // state 可以为函数,也可以是对象
        var newModule = new Module(rawModule, runtime);
        if (path.length === 0) {
            this.root = newModule;
        } else {
            var parent = this.get(path.slice(0, -1));
            parent.addChild(path[path.length - 1], newModule);
        }
        // 创建多个 modules 数组形式
        // 正常情况一个 modules
        // register nested modules
        if (rawModule.modules) {
            // 重复初始化Module
            forEachValue(rawModule.modules, function (rawChildModule, key) {
                // modules 中的对象值
                this$1.register(path.concat(key), rawChildModule, runtime);
            });
        }
    };
    // 删除 module 
    ModuleCollection.prototype.unregister = function unregister(path) {
        var parent = this.get(path.slice(0, -1));
        var key = path[path.length - 1];
        if (!parent.getChild(key).runtime) {
            return
        }

        parent.removeChild(key);
    };

Store类

Store类是一个发动机,来执行Module 中的一些事件,commit 执行mutation ,dispatch 执行 action。
Store 值描述
参数值
_committing 布尔值 标记作用
plugins 插件类型,调用暴露的mutation钩子函数
strict 布尔值,严格模式的情况下只能通过mutation 进行修改state,但是会影响性能,不建议在发布模式下使用
_actions 对象类型 异步事件
_actionSubscribers 数组类型 异步事件调用前派发before回调,调用完成后 after回调
_mutations 同步事件对象
_wrappedGetters getters 存储对象
_modules ModuleCollection 对象
_modulesNamespaceMap module 中 namespaced 的对象存入
_subscribers 同步事件派发
_watcherVM 一个新的Vue 对象
state 全局 state modules 中的用键对值展示
函数
commit 同步执行 先执行mutations中的函数,在派发 _subscribers中的事件
dispatch 异步执行 先执行_actionSubscribers 中带有before 的事件,在执行用Promise.all 执行 _actions中的函数,最后执行after 派发事件
subscribe _subscribers 存入mutation 订阅事件
subscribeAction _actionSubscribers 存入 action 订阅事件
watch state 中的数据进行监听
replaceState 修改 state 值
registerModule 新增module 值,根据第三个参数options.preserveState 来进行是否覆盖之前存在的值,true 不覆盖,false 覆盖,默认false
unregisterModule 去除指定的 module
hotUpdate 热加载
_withCommit 标记回调,为了严格模式而生
    var prototypeAccessors$1 = {state: {configurable: true}};
    prototypeAccessors$1.state.get = function () {
        return this._vm._data.?state
    };

    prototypeAccessors$1.state.set = function (v) {
        {
            assert(false, "use store.replaceState() to explicit replace store state.");
        }
    };
    // 触发 mutation 事件
    Store.prototype.commit = function commit(_type, _payload, _options) {
        var this$1 = this;

        // check object-style commit
        var ref = unifyObjectStyle(_type, _payload, _options);
        var type = ref.type;
        var payload = ref.payload;
        var options = ref.options;

        var mutation = {type: type, payload: payload};
        var entry = this._mutations[type];
        if (!entry) {
            {
                console.error(("[vuex] unknown mutation type: " + type));
            }
            return
        }
        this._withCommit(function () {
            entry.forEach(function commitIterator(handler) {
                handler(payload);
            });
        });
        // 事件派发
        this._subscribers.forEach(function (sub) {
            return sub(mutation, this$1.state);
        });

        if (
            options && options.silent
        ) {
            console.warn(
                "[vuex] mutation type: " + type + ". Silent option has been removed. " +
                'Use the filter functionality in the vue-devtools'
            );
        }
    };
    // 触发action 事件
    Store.prototype.dispatch = function dispatch(_type, _payload) {
        var this$1 = this;

        // check object-style dispatch
        var ref = unifyObjectStyle(_type, _payload);
        var type = ref.type;
        var payload = ref.payload;

        var action = {type: type, payload: payload};
        var entry = this._actions[type];
        if (!entry) {
            {
                console.error(("[vuex] unknown action type: " + type));
            }
            return
        }

        try {
            this._actionSubscribers
                .filter(function (sub) {
                    return sub.before;
                })
                .forEach(function (sub) {
                    return sub.before(action, this$1.state);
                });
        } catch (e) {
            {
                console.warn("[vuex] error in before action subscribers: ");
                console.error(e);
            }
        }

        var result = entry.length > 1
            ? Promise.all(entry.map(function (handler) {
                return handler(payload);
            }))
            : entry[0](payload);

        return result.then(function (res) {
            try {
                this$1._actionSubscribers
                    .filter(function (sub) {
                        return sub.after;
                    })
                    .forEach(function (sub) {
                        return sub.after(action, this$1.state);
                    });
            } catch (e) {
                {
                    console.warn("[vuex] error in after action subscribers: ");
                    console.error(e);
                }
            }
            return res
        })
    };
    // 同步事件 订阅
    Store.prototype.subscribe = function subscribe(fn) {
        return genericSubscribe(fn, this._subscribers)
    };
    // 异步事件订阅
    Store.prototype.subscribeAction = function subscribeAction(fn) {
        var subs = typeof fn === 'function' ? {before: fn} : fn;
        return genericSubscribe(subs, this._actionSubscribers)
    };
    // state 数据进行监听
    Store.prototype.watch = function watch(getter, cb, options) {
        var this$1 = this;

        {
            assert(typeof getter === 'function', "store.watch only accepts a function.");
        }
        return this._watcherVM.$watch(function () {
            return getter(this$1.state, this$1.getters);
        }, cb, options)
    };
    // 重置 state 值
    Store.prototype.replaceState = function replaceState(state) {
        var this$1 = this;

        this._withCommit(function () {
            this$1._vm._data.?state = state;
        });
    };
    // 新增module,根据options.preserveState 来判断是否覆盖相同的
    Store.prototype.registerModule = function registerModule(path, rawModule, options) {
        if (options === void 0) options = {};

        if (typeof path === 'string') {
            path = [path];
        }

        {
            assert(Array.isArray(path), "module path must be a string or an Array.");
            assert(path.length > 0, 'cannot register the root module by using registerModule.');
        }

        this._modules.register(path, rawModule);
        installModule(this, this.state, path, this._modules.get(path), options.preserveState);
        // reset store to update getters...
        resetStoreVM(this, this.state);
    };
    // 去除指定module 
    Store.prototype.unregisterModule = function unregisterModule(path) {
        var this$1 = this;

        if (typeof path === 'string') {
            path = [path];
        }

        {
            assert(Array.isArray(path), "module path must be a string or an Array.");
        }

        this._modules.unregister(path);
        this._withCommit(function () {
            var parentState = getNestedState(this$1.state, path.slice(0, -1));
            Vue.delete(parentState, path[path.length - 1]);
        });
        resetStore(this);
    };
    // 热加载
    Store.prototype.hotUpdate = function hotUpdate(newOptions) {
        this._modules.update(newOptions);
        resetStore(this, true);
    };
    // 为严格模式而生,_committing 状态来判断
    Store.prototype._withCommit = function _withCommit(fn) {
        var committing = this._committing;
        this._committing = true;
        fn();
        this._committing = committing;
    };

    Object.defineProperties(Store.prototype, prototypeAccessors$1);
个人理解 欢迎探讨,指出不足。