如何将一组扁平化的样本数据转换成适用于Element 级联组件的数据结构

1,036 阅读2分钟

相信很多人都用过Element的Cascader 级联选择器组件

element3.gitee.io/#/zh-CN/com…

根据官方提供的demo代码,如果需要使用该组件,得为Cascader的options属性指定一个选项数组,才能渲染出一个级联选择器。

而options的数组结构必须是符合这样的:

 options: [
    {
        value: '父标签名对应的值',
        label: '父标签名',
        children: [
            {
                 value: '子标签名对应的值',
                 label: '子标签名' ,
                 children: [
                        {
                            value: '孙标签名对应的值', 
                            label: '孙标签名'
                        }
                  ] 
            }
        ]    
    }
]

我们可以看到这种数据结构格式是相互嵌套来展示的。

如果这种数据是动态从后端获取的话,后端同学是不太可能会给我们这样的数据结构,最近我用到了这个组件开发业务的时候,后端给我的就是一组非常扁平化的数据,类似这样。

[    
      {
          "id":"tagId",// 标签ID 
          "parentId": "parentId",// 可选,所属父类ID,为空时表示是最顶层节点  
          "name":"tagName"// 标签名称
    }]

这样是不符合级联组件所展示的数据结构的,我们需要抽取一个通用的方法来转换。

首先,我这边后端给我的数据结构属性名和options数组要求的属性名对不上,所以需要先做一层转换。

let result = await fetchData();

result = result.map(d => {
    return {
        value: d.id,
        label: d.name,
        parentId: d.parentId
    }
})

接着我们通过判断是否有parentId属性来将根节点的对象存入到一个数组,将子节点的对象存入到另一个数组。

function translateDataToTree (data) {    
        let parents = data.filter(value => value.parentId === ''); // 过滤掉所有的子节点    
        let children = data.filter(value => value.parentId !== ''); // 过滤掉所有的非根节点    
        translator(parents, children);    
        return parents;
}

在上面我们过滤完毕之后,定义了一个translator方法,这个方法的作用就是对过滤后的两个数组构成嵌套关系。

function translator (parents, children) {    
          parents.forEach((parent) => {  
               children.forEach((current, index) => { 
                 // 如果当前子节点的父id和父亲自身id 匹配成功,则构建嵌套关系
                 if (current.parentId === parent.value) {  
                     let temp = JSON.parse(JSON.stringify(children)); // 克隆一份子节点
                     temp.splice(index, 1); // 剔除当前的子节点
                     translator([current], temp); // 从当前子节点出发,继续寻找它的后代,递归完毕之后,出栈,
                     // 层层出栈之后,判断父节点有无children属性,有则直接push,无则生成一个数组 
                     if (parent.children) {  
                        parent.children.push(current);
                     } else {
                        parent.children = [current];                
                       }            
                    }});});
                }

接下来,我们实践一下,

首先定义一组扁平化的假数据,其数据结构如下所示

然后我们首先调用数组的map方法转换成级联组件对应的属性名

最后通过调用translateDataToTree方法将这组数据传递给data,得到的结果:

现在这个数据格式已经完全符合级联组件所需要的数据要求了。

如果您有更好的思路,非常欢迎在评论区下方留言。