这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战”
在用 vue 的数据渲染时,经常扁平化的数据并不能很方便的使用在dom循环结构中,对数据进行树形化,能很好的解决这个问题,而不是每次用都需要计算一次用在这里的值应该是哪一个变量。
数据扁平化 这个很简单 就是将数据拍平就好 这里为了记录住结构信息 增加了 id 与 pid 属性。
const json = `...` //原始数据时一个 json字符串 包含从市到村的所有数据 树形结构
function formDataFalatten(data = []){
data = JSON.parse(json) // 树形json -> 扁平数据
let id = 0
const out = []
flatten(data, id)
return out
function flatten(arr,pid = 0) {
arr.map(item => {
item.id = ++id
item.pid = pid
if(Array.isArray(item.children)) {
flatten(item.children, item.id)
}
delete item.children
out.push(item);
})
}
}
扁平数据-> 树形数据的第一种方法,使用过滤器,先将数组中的每个元素的子元素添加到当前元素,然后在将顶级元素返回即可,这种方法每个元素获取自身的子元素时,过滤器都查询了所有的元素,当数据量比较大时,就不够迅速了。
function formDataTreeFilter(data) {
return data.filter(p => {
const _arr = data.filter(c => c.pid === p.id)
_arr.length && (p.children = _arr)
return p.pid === 0
})
}
扁平数据-> 树形数据的第二种方法,先循环一次缓存元素的索引。然后再循环一次,将所有元素添加到对应的父元素下,同时如果是顶级元素,就将其添加到要返回的数组中。最后直接返回这个数组就好了。这种方法在数据量大时足够快,缺点就是代码量较多,数据量小时与第一中方法未拉开差距。
function formDataTree(data) {
const idIndexCache = {} // id : data[index]
data.map((item, index) => { //缓存id索引
idIndexCache[item.id] = index
})
const res = []
data.map(item => { // 添加children
if(item.pid === 0 ) {
res.push(item)
return
}
if(data[idIndexCache[item.pid]].children){
data[idIndexCache[item.pid]].children.push(item)
}else{
data[idIndexCache[item.pid]].children = [item]
}
})
return res
}
转换方法当然不止这两种,这里只列出较常用的。下面来测试一下实际效果。数据就是代码片段1中使用中国所有市到村的树形数据转换的扁平数据。
console.time('1')
console.log(formDataTree(formDataFalatten()))
console.timeEnd('1') // 45.454833984375 ms
console.time('2')
console.log(formDataTreeFilter(formDataFalatten()))
console.timeEnd('2') // 35272.997314453125 ms
第二种与过滤器的差距在数据量很大的时候才有明显差异