手撕Vuex-安裝模組資料

BNTang發表於2023-11-13

前言

根據上一篇,【手寫Vuex】-提取模組資訊,我們已經可以獲取到模組的資訊了,將模組資訊變成了我們想要的資料結構,接下來我們就要根據模組的資訊,來安裝模組的資料。

在上一篇當中我們定義了一個 ModuleCollection 類,這個類的作用就是將模組的資訊轉換成我們想要的資料結構。

接下來我們就要根據這個資料結構來安裝模組的資料。

安裝模組資料

那麼怎麼安裝模組資料呢?首先我們先看一下怎麼安裝資料,在安裝資料之前,我們在建立 Store 的時候我們的 root 也就是根元件已經安裝完畢了,所以我們的根元件就不用安裝了,我們只需要安裝根元件下面的子元件的資料就可以了。

那麼安裝子模組的資料我們怎麼安裝呢?我這裡直接開闢一個全新的方法來處理這件事情,安裝子模組的資料,我們先來看一下程式碼:

// 安裝子模組的資料
this.initModules([], this.modules.root);

initModules(arr, module) {
}

如上我開闢對的方法我們先來看一下這個方法的引數,第一個引數是一個空陣列,第二個引數是我們的根模組。

那麼我們在這個方法裡面要做什麼呢?我們要做的就是安裝子模組的資料,那麼我們怎麼安裝子模組的資料呢?首先我們要知道當前的模組是不是根模組,如果是根模組的話,我們就不用安裝了,因為根模組已經安裝完畢了,我們只需要安裝根模組下面的子模組就可以了。

那麼我們怎麼判斷當前的模組是不是根模組呢?我們可以透過 arr 這個陣列來判斷,如果 arr 這個陣列是空陣列的話,那麼我們就可以判斷當前的模組是根模組,如果不是空陣列的話,那麼我們就可以判斷當前的模組是子模組。

好了我們先上程式碼:

initModules(arr, module) {
    if (arr.length > 0) {
    }

    for (let moduleName in module._children) {
        this.initModules(arr.concat(moduleName), module._children[moduleName]);
    }
}

在 initModules 當中我新增了一個 if,一個 for,if 主要作用就是用於判斷如果當前模組是子模組,那麼就需要將資料安裝到 this.state 上面,對應著:

if (arr.length > 0) {
}

如果當前模組不是子模組,那麼就需要從根模組中取出子模組的資訊來安裝,對應著:

for (let moduleName in module._children) {
    this.initModules(arr.concat(moduleName), module._children[moduleName]);
}

好了我們先不繼續往下寫,我們先來列印一下 arr,看一下 arr 是什麼樣子的,我們來看一下列印的結果:

透過如上結果列印我們就可以很好的根據這個結構來完善我們的程式碼了, 思路是這樣的,如果 arr 是空陣列的話,那麼我們就可以判斷當前的模組是根模組,如果不是空陣列的話,那麼我們就可以判斷當前的模組是子模組。

是子模組的話我們要做的就是將子模組的資料安裝到 this.state 上面,如果是根模組的話,我們就不用安裝了,因為根模組已經安裝完畢了,我們只需要安裝根模組下面的子模組就可以了。

程式碼繼續往下走,我們現在主要編寫的程式碼就是實現 if (arr.length > 0) 這個判斷條件的程式碼,說明是子模組,我們是 arr 列印結果是 [] [home] [account] [account, login] 那麼我們首先要安裝的是 home,然後是 account,然後是 login。

那麼我們怎麼安裝呢?如下:

if (arr.length > 0) {
    let parent = arr.splice(0, arr.length - 1).reduce((state, currentKey) => {
        return state[currentKey];
    }, this.state);
    Vue.set(parent, arr[arr.length - 1], module._state);
}

我們先來看一下這段程式碼,首先我們先來看一下 arr.splice(0, arr.length - 1) 這段程式碼,這段程式碼的作用就是將 arr 陣列的最後一個元素去掉,然後返回一個新的陣列,這個新的陣列就是我們要安裝的模組的父模組的路徑。

然後我們再來看一下 reduce((state, currentKey) => { return state[currentKey]; }, this.state) 這段程式碼,這段程式碼的作用就是根據父模組的路徑來獲取到父模組的資料,然後我們再來看一下 Vue.set(parent, arr[arr.length - 1], module._state) 這段程式碼,這段程式碼的作用就是將子模組的資料安裝到父模組的資料上面。

測試結果

好了我們先來看一下程式碼的執行結果:

總結

好了,這篇文章我們主要是實現了安裝子模組的資料,我們透過一個新的方法來安裝子模組的資料,然後我們透過一個 if 來判斷當前的模組是不是子模組,如果是子模組的話,我們就將子模組的資料安裝到父模組的資料上面,如果不是子模組的話,我們就不用安裝了,因為根模組已經安裝完畢了,我們只需要安裝根模組下面的子模組就可以了。

可能大家對 arr.splice(0, arr.length - 1) 這段程式碼不是很理解,這段程式碼的作用就是將 arr 陣列的最後一個元素去掉,然後返回一個新的陣列,這個新的陣列就是我們要安裝的模組的父模組的路徑。

例如我們的 arr 存放的是 [home] 那麼我們的 arr.splice(0, arr.length - 1) 就會返回一個空陣列,這個空陣列就是我們要安裝的模組的父模組的路徑。

空陣列的話,然後又呼叫了 reduce,這回是空陣列,那麼就會返回 this.state,也就是根模組的資料,然後我們再來看一下 Vue.set(parent, arr[arr.length - 1], module._state) 這段程式碼,這段程式碼的作用就是將子模組的資料安裝到父模組的資料上面。

parent 就是根模組的資料,arr[arr.length - 1] 就是我們要安裝的模組的名稱,module._state 就是我們要安裝的模組的資料。

這是沒有層級巢狀的字模組安裝的情況,我們再來看一個有層級巢狀的子模組安裝的情況,例如我們的 arr 存放的是 [account, login] 那麼我們的 arr.splice(0, arr.length - 1) 就會返回一個 [account] 陣列,這個陣列就是我們要安裝的模組的父模組的路徑。

然後我們再來看一下 reduce((state, currentKey) => { return state[currentKey]; }, this.state) 這段程式碼,這段程式碼的作用就是根據父模組的路徑來獲取到父模組的資料,例如我們的父模組的路徑是 [account] 那麼我們就會獲取到 account 模組的資料,然後我們再來看一下 Vue.set(parent, arr[arr.length - 1], module._state) 這段程式碼,這段程式碼的作用就是將子模組的資料安裝到父模組的資料上面。

parent 就是 account 模組的資料,arr[arr.length - 1] 就是我們要安裝的模組的名稱,module._state 就是我們要安裝的模組的資料。

好了,這篇文章我們主要是實現了安裝模組的資料,下一篇文章將會實現安裝模組的方法。

相關文章