讲解
原始数据
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)
}
}
}
}