在写小程序项目时,自定义了一个组织机构树形展示组件,后端接口返回的组织机构数据是一维数组。需要在前端转换成树形结构的数据,并且添加一些节点的树形,比如是否为叶子节点,节点是否展开等,在自定义的组件中通过这些属性,做出友好的用户交互效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script>
var arr = [
{ id: 0, pid: null, text: "父级" },
{ id: 1, pid: 0, text: "一级1" },
{ id: 2, pid: 0, text: "一级2" },
{ id: 3, pid: 1, text: "二级1-1" },
{ id: 4, pid: 1, text: "二级1-2" },
{ id: 5, pid: 2, text: "二级2-1" },
{ id: 6, pid: 2, text: "二级2-2" },
{ id: 7, pid: 3, text: "三级1-1-1" },
{ id: 8, pid: 7, text: "四级1-1-1-1" },
{ id: 9, pid: 8, text: "五级1-1-1-1-1" },
{ id: 10, pid: 9, text: "六级1-1-1-1-1" },
];
let arrayToTree = function (dataArr, rootId) {
let arr = JSON.parse(JSON.stringify(dataArr));
// 获取所有顶级分类,然后组成数组
let parents = arr.filter((v) => v.pid === rootId);
// 获取所有非顶级分类,组成数组
let children = arr.filter((v) => v.pid !== rootId);
// 定义递归方法, 传入参数,父级数组,和子集数组
function dataToTree(p, c) {
// 循环遍历父级数组
p.forEach((p_v) => {
// 循环遍历子集数组
p_v.isOpen = false;
c.forEach((c_v, c_i) => {
// 判断当前的子项是否为当前的父项的子元素
if (c_v.pid === p_v.id) {
// 如果是那么判断当前,当前父类项是否有children 字段
if (!p_v.children) {
// 如果没有初始化为空数组
p_v.children = [];
c_v.isLeaf = true;
}
// 然后把当前的子类项推到父类的children数组中
p_v.children.push(c_v);
// 在执行递归调用当前方法,把当前子类项以数组的形式作为第一个参数传入,然后把所有的子集数组作为第二个参数传入,从新遍历所有子类数组中是否有当前子类的下一级
// dataToTree([c_v], children);
p_v.isLeaf = false;
c_v.isLeaf = true;
/* 为了减少遍历的次数可以把当前项从子类型中删除 */
// 然后把所有的子集数组深拷贝一份,因为数组中的项是对象属于引用类型的
let _c = JSON.parse(JSON.stringify(c));
//然后把当前子类项从整体的子类数组中剔除
_c.splice(c_i, 1);
// 在执行递归调用当前方法,把当前子类项以数组的形式作为第一个参数传入,然后把所有的子集数组作为第二个参数传入,从新遍历所有子类数组中是否有当前子类的下一级
dataToTree([c_v], _c);
}
c_v.isOpen = false;
});
});
}
dataToTree(parents, children);
return parents;
};
let getTree = arrayToTree(arr, null);
console.log(getTree);
</script>
</head>
<body></body>
</html>
原创文章,作者:ZERO,如若转载,请注明出处:https://www.edu24.cn/course/array-to-tree-js.html