树形数据,修改节点属性

在项目中遇到一个难点,纠结了一整天,凌晨算是把这个算法给折腾出来了,用比较笨的方法实现的,如果有更好的方法,欢迎各位大佬纠正。

场景是这样的:公司的部门数据是个树形数据,而我从后端拿到的启用的部门只是一个数组id,因此要把树形数据里的对应id元素下的disabled放开。同时该节点下还有子节点的,也要把子节点设置为可用。

遍历修改树形数据都知道用递归,然而这次传入的不是单一的id,而是一个id数组,如果单纯遍历id再遍历数组就会将已经修改的元素又改回去,同时要修改的还不止当前节点,子节点也要一并修改。所以场景比较复杂。

我的实现思路是:先遍历id数组,在id数组下调用递归函数,递归函数需要传入3个参数,参数1是部门数据,参数2是当前的id,最关键的是参数3,是当前节点的上一节父节点,查找上一节父节点,我在网上找了个方法并修改了一下,只让它返回当前节点的上一个父节点。

// 树形数据
let arr = [
    {
        id: 1,
        label: '1',
        dis: true,
        children: [
            {
                id: 11,
                label: '1.1',
                dis: true,
                children: [
                    {
                        id: 111,
                        label: '1.1.1',
                        dis: true,
                        children: [
                            {
                                id: 1111,
                                label: '1.1.1.1',
                                dis: true,
                            },
                            {
                                id: 1112,
                                label: '1.1.1.2',
                                dis: true,
                            },
                        ]
                    },
                    {
                        id: 112,
                        label: '1.1.2',
                        dis: true,
                    },
                ]
            },
            {
                id: 12,
                label: '1.2',
                dis: true,
                children: [
                    {
                        id: 121,
                        label: '1.2.1',
                        dis: true,
                    },
                    {
                        id: 122,
                        label: '1.2.2',
                        dis: true,
                    },
                ]
            }
        ]
    }
]
// 要修改的id值数组
let list = [111, 121]

const fn1 = (arr, list) => {
    // 上级父节点查询函数
    function findParentArr(targetId) {
        const ids = []
        function getParent(sources) {
            if (Array.isArray(sources)) {
                return sources.find(elm => {
                    let rs = getParent(elm)
                    if (rs) {
                        ids.push(elm)
                    }
                    return rs
                })
            }
            if (sources.id === targetId) {
                return true
            }
            if (Array.isArray(sources.children)) {
                return getParent(sources.children)
            }
        }
        getParent(arr)
        if (ids.length === 1) return ids[0];
        else return ids[1]
    }

    const fn = (arr, id, pNode) => {
        arr.forEach((item) => {
            // 每次递归进来都给他传入一个父节点
            pNode = findParentArr(item.id)
            // 三个判断条件, id是否相等,当前dis是否已经为false,防止修改已经修改的节点,上一级父节点
            // 父节点ids为false,直接让该节点设置成false;父节点不满足则检测其他两个条件是否满足
            if (item.id === id || !item.dis || pNode) {
                if (!pNode.dis) {
                    item.dis = false
                } else {
                    item.dis = !(item.id === id || !item.dis)
                }
            }
            if (item.children && item.children.length > 0) {
                fn(item.children, id, pNode)
            }
        })
    }
    list.forEach((id) => {
        // 初始父节点为Null,从头节点开始
        fn(arr, id, null)
    })
}
fn1(arr, list)
console.log(arr);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值