基於Vuex從零實現本身的Vuez插件-moduleCollection(五)

在前面,咱們已經實現了Vuex中的getters,mutationsactions,如今,咱們來介紹如下modules.
對於使用單一狀態樹,應用的全部狀態會集中到一個比較大的對象。當應用變得很是複雜時,store 對象就有可能變得至關臃腫。javascript

爲了解決以上問題,Vuex 容許咱們將 store 分割成模塊(module)。每一個模塊擁有本身的 statemutationactiongetter、甚至是嵌套子模塊——從上至下進行一樣方式的分割:java

let a = {
    state:{
        name:'a',
        age:18
    },
    modules:{a1,a2,a3},
    getters:{
        getAlpha(state){
            return state.name
        },
        getAge(state){
            return state.age
        }
        
    }
    ...// mutations
    ...// actions
}
let b = {
    state:{
        name:'b'
    },
    modules:{b1,b2,b3},
    getters:{
        getName(state){
            return state.name
        }
    }
    ...// mutations
    ...// actions
}
let rootModule = {
    state:{
        name:'iamsmiling'
    },
    modules:{a,b},
    getters{
        getName(state){
            return state.name
        }
    }
    ...// mutations
    ...// actions
}
// 爲了不代碼太過冗餘,這裏沒有給出a1,a2,a3,b1,b2,b3的定義
let store = new Store(rootModule)
複製代碼

根據上面的代碼結構,畫出咱們的state狀態樹數組

root
                /      \
              a         b
            / | \     /  | \
           a1 a2 a3  b1  b2  b3
           .....// 固然a1,a2,a3,b1,b2,b3也可能存在子模塊
複製代碼

Vuex中,咱們想要調用子模塊的getters,咱們是這樣子進行調用的
store.getters.getAge
咦,等等,root中的getters並無定義getAge啊,爲何能夠這樣調用嗎,調用形式不該該長這樣子的嘛?
store.modules.a.gettters.getAge嘛,搞不懂,搞不懂....bash

Ok好吧,那咱們如今就來解釋以,原生Vuex中能夠store.getters.getAge這種形式調用的緣由,其實也很簡單,Vuex不過是將子模塊中的state/getters/mutations/actions所有安裝到了root上。這樣講或許有些乾澀難懂,那麼,咱們一樣以上面的例子來進行說明:ui

root = { state:{...} ,modules:{a,b},getters:{getName}
 a = {state:{...},getters:{getAlpha,getAge}}
 從上面能夠看出,root中的getters只有getName,a的getters中包括getAlpha,getAge.
 所謂模塊安裝,不過是子模塊中的state/getters/mutations/actions定義在root上。
 通過模塊安裝後,在root的getter中,就包含了getName,getAlpha,getAge
複製代碼

在理解上面的東西以後。咱們明白,接下來咱們的工做就是進行模塊安裝....this

不過,在進行模塊安裝以前,咱們必須先作一項工做,就是進行模塊收集,明確具體有哪些模塊...spa

爲了方便收集模塊,咱們來首先對用戶傳進來的數據進行格式化處理:code

{
    raw:rootModule,
    state:{name:'iamsmiling'}
    children:{
        a:{
            raw:a,
            state:{ name:'a',age:18},
            children:{a1,a2,a3}
            getters:{getAlpha,getAge} //這裏進行了簡寫
        }
        b:{
            raw:b,
            state:{name:'b'},
            children:{b1,b2,b3}
            getters:{getName} //這裏進行了簡寫
        }
    },
    getters:{getName}//這裏進行了簡寫
}
複製代碼

定義一個類,進行模塊收集對象

class ModuleCollection{
    constructor(options){
        this.register([],options) // 註冊模塊
    }
    register(path,rootModule){
        let newModule = {
            raw: rootModule,
            children:{},
            state:rootModule.state
        }
        if(!path.length){
            this.root = newModule
        }else{
            let parent = path.slice(0,-1).reduce((root,current)=>{
                return this.root.children[current]
            },this.root)
            parent.children[path[path.length-1]] = newModule
        }
        if(rootModule.modules){//若是存在modules選項說明存在子模塊
            forEach(rootModule.modules,(name,module)=>{
                this.register(path.concat(name),module)  // 使用遞歸收集模塊 
                // 使用例子解析
                // 第一次遍歷 this.register([a],a) 
                // newModule={raw:a,children:{},state:a.state}
                // path.silce(0,-1) ==> []
                // parent = this.root 
                // this.root[a] =a
                // this.register([a,a1],a1)
                // newModule = {raw:a1,children:{},state:a1.state}
                // path.slice(0,-1) = [a]
                //[a].reduce ===> this.root.children[a]
                // parent = a
                ...
                // 第二次遍歷 this.register([b],b)
                // newModule={raw:b,children:{},state:b.state}
                // path.slice(0,-1) ==> [a]
                // parent = this.root
                // this.root[b] = b
                ...
            }) 
        }
    }
}
複製代碼

注意事項遞歸

  • concat返回新數組,slice返回新數組,不改變原數組
  • reduce,若是數組爲空,會直接返回咱們傳入的初始值 到目前爲止,模塊收集功能也實現了...
相關文章
相關標籤/搜索