You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用递归实现树形复选框联动切换 | 递归问题求解

树形复选框任意深度递归联动实现

核心逻辑拆分

整个联动逻辑拆成两个独立的递归流程,适配任意嵌套深度的树形结构:

  • 自上而下联动:点击节点切换状态后,递归遍历当前节点的所有嵌套子节点,将子节点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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:48:52