【手写Vuex】-手撕Vuex-安装模块数据

2023-11-19 00:17:04 浏览数 (2)

前言

根据上一篇,【手写Vuex】-提取模块信息,我们已经可以获取到模块的信息了,将模块信息变成了我们想要的数据结构,接下来我们就要根据模块的信息,来安装模块的数据。

在上一篇当中我们定义了一个 ModuleCollection 类,这个类的作用就是将模块的信息转换成我们想要的数据结构。

接下来我们就要根据这个数据结构来安装模块的数据。

安装模块数据

那么怎么安装模块数据呢?首先我们先看一下怎么安装数据,在安装数据之前,我们在创建 Store 的时候我们的 root 也就是根组件已经安装完毕了,所以我们的根组件就不用安装了,我们只需要安装根组件下面的子组件的数据就可以了。

那么安装子模块的数据我们怎么安装呢?我这里直接开辟一个全新的方法来处理这件事情,安装子模块的数据,我们先来看一下代码:

代码语言:javascript复制
// 安装子模块的数据
this.initModules([], this.modules.root);

initModules(arr, module) {
}

如上我开辟对的方法我们先来看一下这个方法的参数,第一个参数是一个空数组,第二个参数是我们的根模块。

那么我们在这个方法里面要做什么呢?我们要做的就是安装子模块的数据,那么我们怎么安装子模块的数据呢?首先我们要知道当前的模块是不是根模块,如果是根模块的话,我们就不用安装了,因为根模块已经安装完毕了,我们只需要安装根模块下面的子模块就可以了。

那么我们怎么判断当前的模块是不是根模块呢?我们可以通过 arr 这个数组来判断,如果 arr 这个数组是空数组的话,那么我们就可以判断当前的模块是根模块,如果不是空数组的话,那么我们就可以判断当前的模块是子模块。

好了我们先上代码:

代码语言:javascript复制
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 上面,对应着:

代码语言:javascript复制
if (arr.length > 0) {
}

如果当前模块不是子模块,那么就需要从根模块中取出子模块的信息来安装,对应着:

代码语言:javascript复制
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。

那么我们怎么安装呢?如下:

代码语言:javascript复制
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) 这段代码,这段代码的作用就是将子模块的数据安装到父模块的数据上面。

测试结果

好了我们先来看一下代码的执行结果:

我们的数据绑定好了,我们看看页面上是否可以展示对应模块的数据如下图:

可以看到是可以的,ok,完美,记得展示数据的时候需要将 getters,mutations,注释掉,不然的话就会报错,我还没有实现,我们下一篇来完成这个功能。

总结

好了,这篇文章我们主要是实现了安装子模块的数据,我们通过一个新的方法来安装子模块的数据,然后我们通过一个 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 就是根模块的数据,arrarr.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 模块的数据,arrarr.length - 1 就是我们要安装的模块的名称,module._state 就是我们要安装的模块的数据。

好了,这篇文章我们主要是实现了安装模块的数据,下一篇文章将会实现安装模块的方法。

最后

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞