模块收集

  1. vuex/module/module-collection.js
    import { forEach } from '../util'
    import Module from './module';
    
    class ModuleCollection {
        constructor(options) {
            // 对数据进行格式化操作
            // this.root = {
            //     _raw: '用户定义的模块',
            //     state: '当前模块自己的状态',
            //     _children: { // 孩子列表
            //         a: {
            //             _raw: '用户定义的模块',
            //             state: '当前模块自己的状态',
            //             _children: { // 孩子列表
            //                 e: {}
            //             }
            //         },
            //         c: {
    
            //         }
            //     }
            // }
            this.root = null;
            this.register([], options); // 创建一个栈结构,为了记录父子关系(上一级为下一级的父亲)
        }
        register(path, rawModule) {
            let newModule = new Module(rawModule)
            rawModule.newModule = newModule; // 自定义属性
    
            if (path.length == 0) {
                this.root = newModule
            } else {
                // 找父亲:从根节点依次向下查找
                let parent = path.slice(0, -1).reduce((memo, current) => {
                    return memo.getChild(current)
                }, this.root);
    
                parent.addChild(path[path.length - 1], newModule);
                // 根据当前注册的key ,将他注册到对应的模块的儿子处
            }
    
            // 注册完毕当前模块,在进行注册根模块 
            // 用户进行了 modules 模块化操作
            if (rawModule.modules) {
                forEach(rawModule.modules, (module, key) => {
                    // 递归遍历,将 modules 格式化成上述的树形结构
                    // 此处 path.concat(key) 会返回一个新 [],不会存在引用问题(此处是深度优先遍历)
                    this.register(path.concat(key), module);
                })
            }
        }
    }
    
    export default ModuleCollection
    
  2. vuex/module/module.js
    import { forEach } from '../util'
    class Module {
        constructor(rawModule) {
            this._raw = rawModule;
            this._children = {};
            this.state = rawModule.state
    
            // {
            //     _raw:rootModule,
            //     _children:{},
            //     state:rootModule.state
            // }
        }
        getChild(childName) {
            return this._children[childName]
        }
        addChild(childName, module) {
            this._children[childName] = module
        }
        forEachGetter(cb) {
            this._raw.getters && forEach(this._raw.getters, cb)
        }
        forEachMutation(cb) {
            this._raw.mutations && forEach(this._raw.mutations, cb)
        }
        forEachAction(cb) {
            this._raw.actions && forEach(this._raw.actions, cb)
        }
        forEachChildren(cb) {
            this._children && forEach(this._children, cb)
        }
    
        // 用于标识他自己是否写了 namesapced
        get namespaced() {
            // module.namespaced
            return !!this._raw.namespaced;
        }
    }
    
    export default Module
    

模块安装、模块实现

import { Vue } from './install'
import ModuleCollection from './module/module-collection';
import { forEach } from './util';


function installModule(store, rootState, path, module) { //  a/b/c/d
    // 需要循环当前模块的

    // module.state => 放到rootState对应的儿子里
    if (path.length > 0) { // 儿子模块 
        // 需要找到对应父模块,将状态声明上去
        // {name:'zf',age:'12',a:aState}
        let parent = path.slice(0, -1).reduce((memo, current) => {
            return memo[current];
        }, rootState);
        // 对象新增属性不能导致重新更新视图
        Vue.set(parent, path[path.length - 1], module.state);
    }
    module.forEachGetter((fn, key) => {
        store.wrapperGetters[key] = function () {
            return fn.call(store, module.state);
        }
    });
    module.forEachMutation((fn, key) => { // {myAge:[fn,fn]}
        store.mutations[key] = store.mutations[key] || [];
        store.mutations[key].push((payload) => {
            return fn.call(store, module.state, payload)
        })
    });
    module.forEachAction((fn, key) => {
        store.actions[key] = store.actions[key] || [];
        store.actions[key].push((payload) => {
            return fn.call(store, store, payload)
        })
    });
    module.forEachChildren((child, key) => {
        installModule(store, rootState, path.concat(key), child);
    });
}
class Store {
    constructor(options) {
        // 对用户的模块进行整合 
        // 当前格式化完毕的数据 放到了this._modules里
        this._modules = new ModuleCollection(options); // 对用户的参数进行格式化操作
        this.wrapperGetters = {}
        this.getters = {}; // 我需要将模块中的所有的getters,mutations,actions进行收集
        this.mutations = {};
        this.actions = {};
        const computed = {};
        // 没有namespace的时候 getters都放在根上 ,actions,mutations 会被合并数组
        let state = options.state;
        installModule(this, state, [], this._modules.root);
        forEach(this.wrapperGetters, (getter, key) => {
            computed[key] = getter;
            Object.defineProperty(this.getters, key, {
                get: () => this._vm[key]
            })
        });
        this._vm = new Vue({
            data: {
                $$state: state
            },
            computed
        });

        console.log(this.getters, this.mutations, this.actions)
    }

    get state() {
        return this._vm._data.$$state
    }
    commit = (mutationName, payload) => { // 发布
        this.mutations[mutationName] && this.mutations[mutationName].forEach(fn => fn(payload))
    }
    dispatch = (actionName, payload) => {
        this.actions[actionName] && this.actions[actionName].forEach(fn => fn(payload))
    }
}
// state getters action mutation  (modules 分层)
export default Store;
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 模块收集
  2. 2. 模块安装、模块实现