递归映射树增删监控

讲解

原始数据

let arr = [
    {"id": 2, "parentId": 1, "name": "Fruits"},
    {"id": 3, "parentId": 2, "name": "apple"},
    {"id": 4, "parentId": 2, "name": "orange"},
    {"id": 5, "parentId": 2, "name": "tomato"},
    {"id": 6, "parentId": 1, "name": "Vegetables"},
    {"id": 7, "parentId": 6, "name": "carrot"},
    {"id": 8, "parentId": 6, "name": "cabbage"},
    {"id": 9, "parentId": 6, "name": "potato"},
    {"id": 10, "parentId": 6, "name": "lettuce"},
    {"id": 11, "parentId": 0, "name": "Cars"},
    {"id": 13, "parentId": 8, "name": "Cars"},
    {"id": 1, "parentId": 0, "name": "Foods"},
];

parentId 为0 是第一级别

生成映射树const tree = convert(arr);

[
    {
        "idIP": 11,
        "ip": {
            "id": 11,
            "parentId": 0,
            "name": "Cars"
        },
        "children": []
    },
    {
        "idIP": 1,
        "ip": {
            "id": 1,
            "parentId": 0,
            "name": "Foods"
        },
        "children": [
            {
                "idIP": 2,
                "ip": {
                    "id": 2,
                    "parentId": 1,
                    "name": "Fruits"
                },
                "children": [
                    {
                        "idIP": 3,
                        "ip": {
                            "id": 3,
                            "parentId": 2,
                            "name": "apple"
                        },
                        "children": []
                    },
                    {
                        "idIP": 4,
                        "ip": {
                            "id": 4,
                            "parentId": 2,
                            "name": "orange"
                        },
                        "children": []
                    },
                    {
                        "idIP": 5,
                        "ip": {
                            "id": 5,
                            "parentId": 2,
                            "name": "tomato"
                        },
                        "children": []
                    }
                ]
            },
            {
                "idIP": 6,
                "ip": {
                    "id": 6,
                    "parentId": 1,
                    "name": "Vegetables"
                },
                "children": [
                    {
                        "idIP": 7,
                        "ip": {
                            "id": 7,
                            "parentId": 6,
                            "name": "carrot"
                        },
                        "children": []
                    },
                    {
                        "idIP": 8,
                        "ip": {
                            "id": 8,
                            "parentId": 6,
                            "name": "cabbage"
                        },
                        "children": [
                            {
                                "idIP": 13,
                                "ip": {
                                    "id": 13,
                                    "parentId": 8,
                                    "name": "Cars"
                                },
                                "children": []
                            }
                        ]
                    },
                    {
                        "idIP": 9,
                        "ip": {
                            "id": 9,
                            "parentId": 6,
                            "name": "potato"
                        },
                        "children": []
                    },
                    {
                        "idIP": 10,
                        "ip": {
                            "id": 10,
                            "parentId": 6,
                            "name": "lettuce"
                        },
                        "children": []
                    }
                ]
            }
        ]
    }
]

我们发现我们对原数据进行增删无法对原数组进行监控, 需要添加增删的监控

const arr1 = new Proxy(arr, {...}

完整代码如下

let arr = [
    {"id": 2, "parentId": 1, "name": "Fruits"},
    {"id": 3, "parentId": 2, "name": "apple"},
    {"id": 4, "parentId": 2, "name": "orange"},
    {"id": 5, "parentId": 2, "name": "tomato"},
    {"id": 6, "parentId": 1, "name": "Vegetables"},
    {"id": 7, "parentId": 6, "name": "carrot"},
    {"id": 8, "parentId": 6, "name": "cabbage"},
    {"id": 9, "parentId": 6, "name": "potato"},
    {"id": 10, "parentId": 6, "name": "lettuce"},
    {"id": 11, "parentId": 0, "name": "Cars"},
    {"id": 13, "parentId": 8, "name": "Cars"},
    {"id": 1, "parentId": 0, "name": "Foods"},
];

//转化树  parentId=0 是顶级
function convert(arr, id = 0) {
    let res = [];
    for (let i = 0; i < arr.length; i++) {
        if (arr[i].parentId == id) {
            let obj = {};
            obj.idIP = arr[i].id;
            obj.ip = arr[i];
            res.push(obj);
            let func = convert.bind();
            obj.children = func(arr, arr[i].id);
        }
    }
    return res;
}

// splice 索引问题
// 第一个参数
const computeStartIndex = (startIndex, len) => {
    // 处理索引负数的情况
    if (startIndex < 0) {
        return startIndex + len > 0 ? startIndex + len : 0;
    }
    return startIndex >= len ? len : startIndex;
}
//第二个参数
const computeDeleteCount = (startIndex, len, deleteCount, argumentsLen) => {
    // 删除数目没有传,默认删除startIndex及后面所有的
    if (argumentsLen === 1)
        return len - startIndex;
    // 删除数目过小
    if (deleteCount < 0)
        return 0;
    // 删除数目过大
    if (deleteCount > len - deleteCount)
        return len - startIndex;
    return deleteCount;
}

// 树
const tree = convert(arr);
// 监控数组的增删
const arr1 = new Proxy(arr, {
    get(target, prop) {
        const val = target[prop];
        if (typeof val === 'function') {
            if (['push', 'unshift', 'pop', 'shift', 'splice'].includes(prop)) {
                return function () {
                    if (['unshift', 'push'].includes(prop)) {
                        for (let key in arguments) {
                            if (arguments[key].id) {
                                let obj1 = {idIP: arguments[key].id, ip: arguments[key], children: []};
                                if (arguments[key].parentId === 0) {
                                    prop === 'push' ? tree.push(obj1) : tree.unshift(obj1)
                                } else {
                                    searchId(tree, obj1, obj1.ip.parentId, prop)
                                }
                            }
                        }
                    }
                    if (prop === 'shift') {
                        searchId(tree, {}, arr[0].idIP, 'shift')
                    }
                    if (prop === 'pop') {
                        searchId(tree, {}, arr[arr.length - 1].id, 'pop')
                    }
                    if (prop === 'splice' && arguments.length > 0) {
                        // 处理索引负数的问题
                        let arr2 = arr1.slice(computeStartIndex(arguments[0], arr.length), computeDeleteCount(arguments[0], arr.length, arguments[1], arguments.length))
                        // 删除
                        for (let i = 0; i < arr2.length; i++) {
                            searchId(tree, {}, arr2[i].id, 'splice')
                        }
                        // 增加
                        if (arguments.length > 2) {
                            for (let key = 2; key < arguments.length; key++) {
                                if (arguments[key].id) {
                                    let obj1 = {idIP: arguments[key].id, ip: arguments[key], children: []};
                                    if (arguments[key].parentId === 0) {
                                        tree.push(obj1)
                                    } else {
                                        searchId(tree, obj1, obj1.ip.parentId, 'push')
                                    }
                                }
                            }
                        }
                    }
                    return Array.prototype[prop].apply(target, arguments);
                }
            }
            return val.bind(target);
        }
        return val;
    }
});

// 转化树响应转化
const searchId = (tree, obj, parentId, str) => {
    for (let i = 0; i < tree.length; i++) {
        if (tree[i].idIP === parentId) {
            if (str === 'push') {
                tree[i].children.push(obj)
            } else if (str === 'unshift') {
                tree[i].children.unshift(obj)
            } else if (str === 'pop') {
                tree.pop();
            } else if (str === 'shift') {
                tree.shift();
            } else if (str === 'splice') {
                tree.splice(i, 1)
            }
            return;
        } else {
            if (tree[i].children.length) {
                searchId(tree[i].children, obj, parentId, str)
            }
        }
    }
}
posted @ 2021-05-31 16:16  猫神甜辣酱  阅读(203)  评论(0编辑  收藏  举报