ES5实现一个 Vuex(2)

239 阅读1分钟

上一篇文章已经实现了Vuex de  state, getters, mutations,actions等功能juejin.cn/post/684490…

本篇需要实现 modules 也是 Vuex 重要的 modules

1. 收集模块,ModuleCollection, 先将options 的所有模块收集好,构造出想要的数据结构

// options 中的  modules 如下
modules: {
  a: {     
    state: {      
    name: 'moduleA',      
    count: 100    },    
    mutations: {      
        addModuleA( state, payload ) {         
            state.count += payload      
        }    
    }   
 },   
 b: {     
    state: {       
        name: 'moduleB'     
    }    
 }  
}

收集方法是为了把 modules的结构变成下面的结构

root: {// root其实就是options
    _raw, // 元数据
    _children: {}, // 子模块
    state,//当前模块的 state
}

收集器的构造函数如下

function ModuleCollection (rootModule) {
    this.register([], rootModule)
}

ModuleCollection.prototype.register = function(path, rootModule) {
    let newModule = {
        _raw: rootModule,
        _children: {},
        state: rootModule.state
    }
    // 判断如果是 父模块,就把模块赋值给 root
    if(path.length === 0) {
        this.root = newModule
    }else{
        // 如果有子模块
        let parent = path.slice(0, -1).reduce(function(root, cur){
            return root._children[ cur ]
        }, this.root)
        parent._children[path[path.length - 1]] = newModule
    }
    if(rootModule.modules) {
        forEach(rootModule.modules, function(moduleName, module) {
            this.register(path.concat(moduleName), module)
        }).bind(this)
    }
}

2.安装模块:主要是把之前的 state mutations getters actions注册到  store中 

// 安装模块  
function installModule( store, state, path, rootModule ) {    
// 安装模块的  state    
if( path.length > 0 ) {      
    let parent = path.slice(0, -1).reduce(function(state, cur) {        
        return state[cur]      
    }, state)     
    Vue.set(parent, path[path.length - 1], rootModule.state )    
}    
// 需要递归 将结果挂载 getters, mutations, actions    
var getters = rootModule._raw.getters    
if( getters ) { 
// 给 store 增加了getters 属性      
  forEach(getters, function(key, value) {        
    Object.defineProperty(store.getters, key, {          
        enumerable: true,          
        configurable: true,          
        get: function() {            
            return value( rootModule.state )         
        }        
    })     
  })    
}    
// 处理mutations    
var mutations = rootModule._raw.mutations    
if( mutations ) {      
    forEach(mutations, function(key, value) {        
    store.mutations[key] = store.mutations[key] || []        
    store.mutations[key].push(function(payload) {          
        value(rootModule.state, payload )        
    })      
  })    
}    
// 处理actions    
var actions = rootModule._raw.actions    
if( actions ) {      
    forEach( actions, function(key, value) {        
        store.actions[key] = store.actions[key] || []        
        store.actions[key].push( function(payload) {          
            value(store, payload)        
        })      
    })    
 }    
if( rootModule._children ) {      
    forEach( rootModule._children, function(moduleName, module) {        
        installModule( store, state, path.concat(moduleName), module )      
    })    
  }      
}