数据扁平化 与 数据树形结构化

2,304 阅读2分钟

这是我参与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

第二种与过滤器的差距在数据量很大的时候才有明显差异