解决Angular Material嵌套树全节点展开栈溢出及展开完成验证问题
Angular Material Nested TreeView 大数据集展开问题解决与验证方案
问题背景
在大数据集项目中使用Angular Material的Nested TreeView,由于业务依赖嵌套结构无法切换到更适合大数据场景的Flat TreeView。目前整体运行正常,但调用递归方法展开全部节点时会触发Maximum call stack size exceeded栈溢出错误,同时需要可靠的方法验证所有节点是否已完全展开,尝试过Promise等方案未奏效。
原递归展开代码
expandAllNodes() { this.recursivelyExpandNodes(this.dataSource.data); console.log('done'); } recursivelyExpandNodes(nodes: TreeNode[]) { nodes.forEach(node => { this.treeControl.expand(node); if (node.children) { this.recursivelyExpandNodes(node.children); } }); }
解决方案
1. 替换递归为迭代展开(解决栈溢出)
递归调用深度超过JS引擎栈限制导致溢出,改用迭代方式模拟递归逻辑,避免占用调用栈:
expandAllNodes() { // 用数组模拟栈,存储待处理节点 const nodeStack = [...this.dataSource.data]; while (nodeStack.length > 0) { const currentNode = nodeStack.pop(); if (!currentNode) continue; // 展开当前节点 this.treeControl.expand(currentNode); // 若有子节点,推入栈中等待处理(顺序不影响展开结果) if (currentNode.children && currentNode.children.length > 0) { nodeStack.push(...currentNode.children); } } // 展开完成后执行验证 const allExpanded = this.verifyAllNodesExpanded(); console.log(allExpanded ? '所有节点已展开' : '存在未展开节点'); }
2. 迭代式验证所有节点展开状态
同样用迭代方式遍历所有节点,结合TreeControl的isExpanded方法判断状态,避免递归栈溢出:
verifyAllNodesExpanded(): boolean { const nodeStack = [...this.dataSource.data]; while (nodeStack.length > 0) { const currentNode = nodeStack.pop(); if (!currentNode) continue; // 检查当前节点是否展开 if (!this.treeControl.isExpanded(currentNode)) { console.error('未展开节点:', currentNode); return false; } // 推入子节点继续检查 if (currentNode.children && currentNode.children.length > 0) { nodeStack.push(...currentNode.children); } } return true; }
说明
- 迭代方式通过数组模拟调用栈,不会占用JS引擎的调用栈空间,因此能处理深度极大的嵌套节点结构
- 验证方法直接利用Angular Material TreeControl提供的
isExpandedAPI,无需额外维护状态,确保准确性
内容的提问来源于stack exchange,提问作者Anna
相关产品推荐
相关产品推荐

