笔者在写树形下拉框组件时需要将扁平数组转换为树形数组,因此便想做一期两种数组相互转换的内容,如有错误恳请指正。
1. 扁平数组 >>> 树形数组
在开发中,获取的数据多数情况下是带有 parent ID 的扁平数组,而我们需要将其转换为树形数组。扁平数组的格式如下所示:扁平数组中,每项主要由 id 和 name 组成,通过 pid 指向对应的父节点。而像“中国”这样的树节点, pid 则为空。
转换为树形数组的思想是:遍历扁平数组中的每项数据,根据 pid 判断当前节点的父节点和子节点。
源码展示:
// .js
const data = [
// 每项主要由id和name组成,而pid指向其父节点的id
// 如果是树节点则对应的pid为空
{ id: '01', name: '中国', pid: ''},
{ id: '02', name: '北京市', pid: '01'},
{ id: '03', name: '海淀区', pid: '02'},
{ id: '04', name: '丰台区', pid: '02'},
{ id: '05', name: '朝阳区', pid: '02'},
{ id: '06', name: '重庆市', pid: '01'},
{ id: '07', name: '渝中区', pid: '06'},
{ id: '08', name: '江北区', pid: '06'},
{ id: '09', name: '四川省', pid: '01'},
{ id: '10', name: '成都市', pid: '09'},
{ id: '11', name: '成华区', pid: '10'},
{ id: '12', name: '武侯区', pid: '10'}
];
function transNormalToTree(array) {
let result = [] //最终存储的结果
// 对数组中的每个对象进行遍历
array.forEach( item => {
// 判断当前节点是否为根节点,如果是则push
if (!item.pid) {
result.push(item)
}
// 将所有pid等于当前id的对象储存在children数组中
let childArray = array.filter(data => data.pid === item.id)
// 判断当前节点是否为叶节点,如果是则退出
if (!childArray.length) {
return
}
// 将符合条件的子数组赋值给当前项的child属性
item.child = childArray
})
return result
}
console.log(transNormalToTree(data))
2. 树形数组 >>> 扁平数组
虽然多数时候需要我们将扁平数组转换为树形数组,但掌握反向转换的方法也很重要。我这里直接将我另一篇文章里的内容贴出来:
树形数组的就是扁平数组反过来的结构,子节点包含在父节点的children属性中。
转换方法有两个参数,一是源数组,二是存放结果的空数组。对源数组进行 forEach 遍历循环:将当前元素 push 进结果数组。其中结果数组的 label 是源数组的 label,value 是源数组的 id 。然后再对当前元素进行判断:如果其有 children 节点,则再次执行 optionData 方法,而参数则是该元素的 children 节点和第一次迭代的 result 。这样直到最后一个元素判断后,返回 result 。
感兴趣的朋友可以看一下这篇文章:组件Element-UI 2实现树形下拉选择框
源码展示:
// Vue .js
cityData: [{
id: 1,
label: '重庆',
children: [{
id: 2,
label: '渝北区'
}]
}, {
id: 3,
label: '北京',
children: [
{ id: 4, label: '海淀区' },
{ id: 5, label: '朝阳区' }
]
}, {
id: 6,
label: '四川',
children: [
{
id: 7,
label: '成都',
children: [
{ id: '8', label: '成华区' }
]
}
]
}]
// .js
optionData(array, result=[]) {
array.forEach(item => {
result.push({label:item.label,value:item.id})
if (item.children && item.children.length !== 0) {
this.optionData(item.children, result)
}
})
return JSON.parse(JSON.stringify(result))
},