如何使用Pipe检测树结构的所有子节点是否全部处于启用状态
代码错误分析与修复
第一个Angular Pipe版本错误点
- 类属性
enabled状态残留:Pipe为单例实例,私有属性enabled不会在每次transform调用时重置,上次计算的结果会污染下一次调用的返回值。 - 子节点校验逻辑错误:遍历子节点时直接将
this.enabled赋值为当前子节点的enabled值,最终结果只会等于最后一个遍历到的子节点的启用状态,无法实现“所有子节点都启用才返回true”的逻辑。
第二个递归函数版本错误点
- for循环提前终止:遍历子节点时直接
return search(child),只会校验第一个子节点就返回结果,其余子节点完全不会被遍历到,只要第一个子节点启用就直接返回true,不管后续是否存在禁用的子节点。 - 误校验父节点状态:你要求排除父节点仅校验子节点,但代码第一行就判断了当前传入节点的
enabled状态,会把父节点本身的状态纳入校验逻辑,不符合需求。
修复后的代码
Angular Pipe版
@Pipe({ name: 'allchildEnabled', pure: false }) export class AllChildEnabledChildPipe implements PipeTransform { transform<T extends ITreeNode>(node: T): boolean { // 直接返回递归结果,不使用类属性存储状态避免污染 return this.search(node); } private search<T extends ITreeNode>(node: T): boolean { // 无后代直接返回true,即所有子节点都满足启用要求 if (!node?.children || node.children.length === 0) { return true; } // 遍历所有子节点,只要有一个不满足就返回false for (const child of node.children) { // 当前子节点禁用,或子节点的后代存在禁用,都返回false if (!child.enabled || !this.search(child)) { return false; } } return true; } }
普通递归函数版
function checkAllChildEnabled(node: any): boolean { if (!node?.children || node.children.length === 0) { return true; } for (const child of node.children) { if (!child.enabled || !checkAllChildEnabled(child)) { return false; } } return true; } // 测试用例 let tree = {id: 1, enabled: true, children: [{id: 2, enabled: true}, {id: 3, enabled: true}, {id: 3, enabled: true, children: [{id: 4, enabled: true}]}]}; console.log(checkAllChildEnabled(tree)); // 输出true
内容的提问来源于stack exchange,提问作者user15361861
相关产品推荐
相关产品推荐

