关于深复制以及平铺数据转为树形结构
-
本次代码背景为后端返回的平铺的组织架构数据需要转换为树形结构,最后面有封装后的代码
-
需要根据cAxis来判断层级,然后根据sortId与pid进行push
- `
//深复制函数
function deepClone(obj) {
function isObject(o) { return (typeof o === 'object' || typeof o === 'function') && o !== null }
if (!isObject(obj)) { throw new Error('非对象') }
let isArray = Array.isArray(obj)
let newObj = isArray ? [...obj] : { ...obj };
Reflect.ownKeys(newObj).forEach(key => { newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key] }); return newObj
};
let newList = deepClone(arrAll);
newList = newList.map((item) => {
item.Id = item.sortId;
item.Name = item.sortName;
//可以按照item.Count去判断是否有必要展示下级
item.IsEnd = item.isEnd;
item.type = type;
item.typeName = Name;
if (!item.IsEnd) {
item.child = [];
}
return item
})
let lastList = [];
newList.forEach(item => {
const str = item.cAxis.split(/\$/);
const index = str.length - 3;
if (lastList[index] && Array.isArray(lastList[index])) {
lastList[index].push(item);
} else {
lastList[index] = [item]
}
})
for (let i = (lastList.length - 1); i > 0; i--) {
lastList[i].forEach(item => {
const str = item.cAxis.match(/\d+/g);
if (lastList[i - 1]) {
lastList[i - 1].forEach(items => {
if (items.sortId === item.pid) {
if (items.child && Array.isArray(items.child)) {
items.child.push(deepClone(item))
} else {
items.child = [deepClone(item)];
}
}
})
}
})
}
`
- 二次封装,主要用于算法的解耦,方便复用
- 数据源如下
- `
const newList = [{
"sortName": "集团单位",
"pid": "0",
"isEndUsed": 0,
"domainEvents": [],
"ownerId": "1807323",
"enterId": "1805435",
"recordId": 0,
"icfo": "0",
"establishTime": "0001-01-01T00:00:00",
"sortId": "2106221744230000109",
"orgCode": "03",
"isMaster": 1,
"createdTime": "2021-06-22T17:44:23",
"cFullName": "集团单位",
"inheritanceId": "636346361736274263",
"sortRank": 0,
"sortRankNum": 2,
"isUseMarket": 0,
"isEnd": 0,
"isUsed": 1,
"createdDate": "0001-01-01T00:00:00",
"iceo": "0",
"isMust": 0,
"cAxis": "$2106221744230000109$",
"sortOrder": 1,
"modifiedDate": "0001-01-01T00:00:00",
"isDel": 0,
"isUseUnit": 1,
"lastUpdateTime": "2022-05-24T13:50:10"
},
{
"sortName": "单位一级",
"pid": "2106221744230000109",
"isEndUsed": 0,
"domainEvents": [],
"ownerId": "1950569",
"enterId": "1805435",
"recordId": 0,
"icfo": "0",
"establishTime": "2021-07-19T00:00:00",
"sortId": "202107200236411553",
"orgCode": "",
"isMaster": 1,
"createdTime": "2021-07-20T10:36:41",
"cFullName": "集团单位/单位一级",
"inheritanceId": "636346361736274263",
"sortRank": 1,
"sortRankNum": 2,
"isUseMarket": 0,
"isEnd": 0,
"isUsed": 1,
"createdDate": "0001-01-01T00:00:00",
"iceo": "0",
"isMust": 0,
"cAxis": "$2106221744230000109$202107200236411553$",
"sortOrder": 1,
"modifiedDate": "0001-01-01T00:00:00",
"isDel": 0,
"isUseUnit": 1,
"lastUpdateTime": "2022-08-19T16:00:13"
},
{
"sortName": "单位二级",
"pid": "202107200236411553",
"isEndUsed": 0,
"domainEvents": [],
"ownerId": "1801976",
"enterId": "1805435",
"recordId": 0,
"icfo": "0",
"establishTime": "2021-07-20T00:00:00",
"sortId": "202107200820254831",
"orgCode": "",
"isMaster": 1,
"createdTime": "2021-07-20T16:20:25",
"cFullName": "集团单位/单位一级/单位二级",
"inheritanceId": "636346361736274263",
"sortRank": 2,
"sortRankNum": 0,
"isUseMarket": 0,
"isEnd": 1,
"isUsed": 1,
"createdDate": "0001-01-01T00:00:00",
"iceo": "0",
"isMust": 0,
"cAxis": "$2106221744230000109$202107200236411553$202107200820254831$",
"sortOrder": 1,
"modifiedDate": "0001-01-01T00:00:00",
"isDel": 0,
"isUseUnit": 1,
"lastUpdateTime": "2021-07-20T16:20:25"
}
];
- 代码二次封装如下
const tilingToTree = (list, option) => {
const deepClone = (obj) => {
function isObject(o) {
return (typeof o === "object" || typeof o === "function") && o !== null;
}
if (!isObject(obj)) {
throw new Error("非对象");
}
let isArray = Array.isArray(obj);
let newObj = isArray
? [...obj]
: {
...obj,
};
Reflect.ownKeys(newObj).forEach((key) => {
newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key];
});
return newObj;
};
// 判断是否为数组,且数组是否有元素
if (!Array.isArray(list) || !list.length) return;
// 为防止数组不可修改
const newList = deepClone(list);
const newOption = option || {
keyName: "",
parentKeyName: "sortId",
childKeyName: "pid",
contactKeyName: "child",
};
// 先创建一个用来根据层级存储数据的数组
const sequenceList = [];
// 遍历数据源,用来根据层级决定在sequenceList数组中存储位置
newList.forEach((item) => {
let hierarchy;
//如有直接显示的层级keyName,其中item[newOption.keyName]直接就是层级
if (newOption.keyName && item[newOption.keyName]) {
// 减一是层级一般从一级开始,但是索引从0开始
hierarchy = item[newOption.keyName] - 1;
} else {
const str = item.cAxis.split(/\$/);
hierarchy = str.length - 3;
}
// 如果数组中对应层级数字的索引存在且是数组,选择直接push
if (sequenceList[hierarchy] && Array.isArray(sequenceList[hierarchy])) {
sequenceList[hierarchy].push(item);
} else {
// 否则将item用数组包裹放到改索引位置
sequenceList[hierarchy] = [item];
}
});
// 此处使用遍历递减,即从层级数字最大的(官小的开始)
for (let i = sequenceList.length - 1; i > 0; i--) {
// 从数组中的最后一个数组开始遍历
sequenceList[i].forEach((item) => {
// 判断它的上级是否存在
if (sequenceList[i - 1]) {
// 遍历他的上级
sequenceList[i - 1].forEach((items) => {
// 如果他上级的sortId等于下级的pid
if (items[newOption.parentKeyName] === item[newOption.childKeyName]) {
//如果上级的child属性存在,且是数组
if (
items[newOption.contactKeyName] &&
Array.isArray(items[newOption.contactKeyName])
) {
items[newOption.contactKeyName].push(deepClone(item));
} else {
items[newOption.contactKeyName] = [deepClone(item)];
}
}
});
}
});
}
// 返回最上级(老板级)
return sequenceList[0];
};
console.log(tilingToTree(newList), "tilingToTree");