唯品秀前端博客

最近遇到个需求,简单描述下需求,就是通过一组循环嵌套数据渲染后的页面,当点击页面某一列数据时候,我可以在当前列的同级插入一条(兄弟)数据,这个就很灵活了,因为数据是无限嵌套,唯一可追寻的就是唯一id了。一时有些懵逼,后来研究下,在此记录一波,该后期还是能遇到的

tree数据源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
let tree = [
    {
        id: 8,
        children: [
            {
                id: 9,
                children: []
            },
            {
                id: 10,
                children: []
            }
        ]
    },
    {
        id: 24,
        children: [
            {
                id: 25,
                children: [
                    {
                        id: 26,
                        children: []
                    }
                ]
            }
        ]
    },
    {
        id: 30,
        children: [
            {
                id: 31,
                children: [
                    {
                        id: 32,
                        children: [
                            {
                                id: 33,
                                children: []
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

方法一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let off = true
function treeFn(treeData, id) {
    treeData.map((item, ind, arr) => {
        if (item.id == id && off) {
            arr.push({
                id: 100,
                children: []
            })
            off = false
        } else if (item.children.length && off) {
            treeFn(item.children, id)
        }
    })
    return tree
}
console.log('tree', treeFn(tree, 32))

方法二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function treeFn(arr, id, p = false) {
    // 往传入的id同级新增节点
    // arr.reduce(
    //     (total, item, index, arr) => {
    //         item.id == id ? (arr.push({ id: 100,children:[] })) : total ? total : treeFn(item.children, id, total)
    //     },
    //     p
    // );
    // return arr

    //获取当前id节点数据
    return arr.reduce(
        (total, item, index, arr) => { return item.id == id ? item : total ? total : treeFn(item.children, id, total) }
        ,
        p
    );
}
console.log(treeFn(tree, 33))

方法三(来自Q群的召唤)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * 根据子级ID在同级中追加数据
 * @param {*} tree 树型数据
 * @param {*} id   查找的节点ID
 * @param {*} node  添加的节点
 */

let addTree = (treeData, nodeId, nodeObj) => {
    if (!Array.isArray(treeData) || treeData.length === 0) {
        return treeData;
    }
    const data = JSON.parse(JSON.stringify(treeData));
    let findParentIdAppend = (tree, id, node, parentId, pushBool) => {
        tree.map(item => {
            if (item.id == id) {
                //这里再次调用是为因为需要通过父级ID再次遍历添加(通过参数pushBool来判断是查找ID还是Push)
                pushBool ? (item.children && item.children.push(node)) : findParentIdAppend(data, parentId, node, parentId, true);
            } else {
                //这里递归是为了查找父级ID
                (item.children && item.children.length > 0) && findParentIdAppend(item.children, id, node, item.id, pushBool);
            }
        })
        return tree;
    }
    return findParentIdAppend(data, nodeId, nodeObj);
}

console.log(addTree(tree, 26, {
  id: 55,
  name: '张三'
}));

根据id删除数组或对象的某一项

1
2
3
4
5
6
7
8
9
10
11
12
13
function deleteNode(id, obj) {
    if (typeof obj !== 'object' || obj === null) {
        return obj
    }
    const arr = Array.isArray(obj) ? [] : {};
    Object.keys(obj).forEach(key => {
        if (id !== obj[key].id) {
            arr[key] = deleteNode(id, obj[key])
        }
    })
    return arr;
}
console.log(deleteNode(24, tree))

小结

只要谈到tree树状结构,那么递归是很难避免的,前面方法一核方法二主要是通过递归+在循环过程中拿到当前循环体的数组arr,通过改变当前子集的arr从而改变了原始数据tree,原理还是根据数据引用类型,两个对象指向的是同一个地址,所以改变其中一个就会改变另一个。

本站所有文章、图片、资源等如无特殊说明或标注,均为来自互联网或者站长原创,版权归原作者所有;仅作为个人学习、研究以及欣赏!如若本站内容侵犯了原著者的合法权益,可联系我们进行处理,邮箱:343049466@qq.com
赞(3) 打赏
标签:

上一篇:

下一篇:

相关推荐

0 条评论关于"tree树形加载-嵌套数据格式的增删查改"

表情

最新评论

    暂无留言哦~~
谢谢你请我吃鸡腿*^_^*

支付宝扫一扫打赏

微信扫一扫打赏