使用递归实现树形复选框联动切换 | 递归问题求解
树形复选框任意深度递归联动实现
核心逻辑拆分
整个联动逻辑拆成两个独立的递归流程,适配任意嵌套深度的树形结构:
- 自上而下联动:点击节点切换状态后,递归遍历当前节点的所有嵌套子节点,将子节点
checked状态和当前节点保持完全一致 - 自下而上联动:从被点击节点开始向上遍历父节点,仅当当前节点是父节点的唯一子节点时,同步父节点的
checked状态,直到遍历到根节点、或遇到存在多个子节点的父节点时终止向上遍历
为了避免每次向上查找父节点都要遍历整棵树,先遍历一次树构建id到节点、id到父节点的映射表,把查找效率提升到O(1)。
完整实现代码
/** * 树形复选框状态联动处理 * @param {Array} treeData 原始树形复选框结构数组 * @param {string|number} clickedNodeId 被用户点击的节点ID * @returns {Array} 联动更新后的树形结构 */ function toggleCheckboxTree(treeData, clickedNodeId) { const nodeMap = new Map(); const parentRelationMap = new Map(); // 第一次递归遍历全树,构建节点索引和父子关系映射 function buildNodeMap(nodes, parentNode = null) { nodes.forEach(node => { nodeMap.set(node.id, node); parentRelationMap.set(node.id, parentNode); if (node.children?.length) buildNodeMap(node.children, node); }); } buildNodeMap(treeData); const clickedNode = nodeMap.get(clickedNodeId); if (!clickedNode) return treeData; // 计算点击后的新状态 const nextCheckedState = !clickedNode.checked; // 向下递归:同步所有子节点状态 function syncChildrenState(node, checkedState) { node.checked = checkedState; if (node.children?.length) { node.children.forEach(child => syncChildrenState(child, checkedState)); } } syncChildrenState(clickedNode, nextCheckedState); // 向上递归:按唯一子节点规则同步父节点状态 function syncParentState(childNodeId) { const parentNode = parentRelationMap.get(childNodeId); // 到达根节点,终止递归 if (!parentNode) return; // 仅当父节点只有当前这一个子节点时,才同步状态并继续向上 if (parentNode.children.length === 1) { parentNode.checked = nextCheckedState; syncParentState(parentNode.id); } } syncParentState(clickedNodeId); return treeData; }
使用示例
// 原始树形数据 const checkboxes = [{ field: 'ARTICLE', id: 41, name: 'Article', parentId: null, checked: false, children: [ { field: 'article.colorCode', id: 42, name: 'Color', parentId: 41, checked: false, children: [ { children: [], field: 'red', id: 43, name: 'red', parentId: 42, checked: false }, ], }, ] }]; // 点击id为43的red节点 toggleCheckboxTree(checkboxes, 43); // 执行后:red、Color、Article三个节点因为是单链路唯一子节点关系,checked都会变成true // 点击id为41的Article节点取消选中 toggleCheckboxTree(checkboxes, 41); // 执行后:Article、Color、red三个节点的checked都会变成false
逻辑说明
- 向下同步逻辑是全量覆盖,不管子节点之前是什么状态,全部和当前点击的节点状态保持一致,符合父子复选框的常规交互
- 向上同步逻辑严格遵循需求:只有当前节点是父节点的唯一子节点时才会触发父节点状态更新,只要某一层父节点存在多个子节点,向上联动会直接终止,不会影响其他分支的节点状态
- 递归逻辑没有写死嵌套层数,不管树有多少层嵌套都可以正常运行
内容的提问来源于stack exchange,提问作者Jake Cano
相关产品推荐
相关产品推荐

