需求: 多层级分组下只有一个图层,删除该图层后删除其所有无图层的祖先分组。 具体见下图。
树形数据结构, 去除多余属性后结构如下: <其中分组id均以 group_开头>
[
{
"name": "分组",
"id": "group_1672303062151",
"title": "分组",
"modules": [
{
"name": "定制标题",
"id": "1608381678943666178"
},
{
"name": "分组",
"id": "group_1672303792251",
"title": "分组",
"modules": [
{
"name": "分组",
"id": "group_1672303794937",
"title": "分组",
"modules": [
{
"name": "分组",
"id": "group_1672303798174",
"title": "分组",
"modules": [
{
"name": "A",
"id": "1608382207992201218"
}
]
}
]
}
]
}
]
}
]
代码实现
export const filterEmptyGroups = (tree) => {
const recursiveFn = (tree) => {
for (let i = 0; i < tree.length; i++) {
const item = tree[i];
if (item.modules && Array.isArray(item.modules) && item.modules.length) {
recursiveFn(item.modules);
}
if (item.id.startsWith("group") && item.modules.length === 0) {
tree.splice(i, 1);
// splice后,不将i--的话,会跳过数组中的项
i--;
}
}
};
recursiveFn(tree);
// 此时引用类型tree已经被改变了,所有引用它的地方都会改变,如果想避免这个问题, 可以将tree深拷贝一份儿再传进来
return tree;
};
下面是最开始写的方法,后来review代码时候,回想了半天,愣是想不起来当时为啥子这样做了(应该不止我一个人有这种情况吧😂):在能拿到x.modules的情况下,还为了获取x.modules而把x传入recursiveFn,着实有点蠢了,哈哈。但是这种憨憨行为值得一记,毕竟很久以后回看的话定会哈哈一笑。
const filterEmptyGroups = tree => {
//递归函数, par为当前
const recursiveFn = (tree, par) => {
tree.forEach((x, i) => {
// 如果modules不为空数组,递归执行
if (x.modules && Array.isArray(x.modules) && x.modules.length) {
recursiveFn(x.modules, x);
}
if (x.id.startsWith("group") && x.modules.length === 0) {
if (par.modules && par.modules.length) {
par.modules.splice(i, 1);
}
}
});
};
recursiveFn(tree, []);
// 执行结束后最外面一层如果为分组的话是删除不到的,所以再过滤一次以去除最外层的空分组
const finalTree = tree.filter((item) =>
item.id.startsWith("group")
? Array.isArray(item.modules) && item.modules.length
: true
);
return finalTree;
};