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

如何在React中实现带嵌套下拉项的优化表格?

嵌套可展开表格行的优化实现思路

一、优化数据结构,实现节点快速定位

当前的树形数组查找节点需要逐层遍历,针对嵌套场景和大数据量,建议改成扁平映射结构:用对象存储所有节点,以节点id作为键,同时给每个节点添加parentId字段明确父子关系,这样无需遍历就能直接定位任意节点,性能大幅提升。

示例结构:

const flatNodes = {
  1: { id: 1, parentId: null, childrens: [10, 11], isExpanded: false },
  10: { id: 10, parentId: 1, childrens: [], isExpanded: false },
  11: { id: 11, parentId: 1, childrens: [12], isExpanded: false },
  12: { id: 12, parentId: 11, childrens: [], isExpanded: false },
  2: { id: 2, parentId: null, childrens: [], isExpanded: false }
};

二、用状态驱动渲染,替代手动DOM操作

React中直接操作DOM添加/删除<tr>极易出错,尤其嵌套场景,建议通过状态控制渲染逻辑:

  • 维护一个expandedIds集合,记录当前展开的节点ID
  • 渲染时通过递归或迭代,根据expandedIds判断是否渲染子节点

核心渲染逻辑示例:

const renderRows = (nodes) => {
  return nodes.flatMap(node => {
    // 渲染当前行
    const row = (
      <tr key={node.id} onClick={() => toggleExpand(node.id)}>
        <td>{node.childrens.length ? (expandedIds.has(node.id) ? '-' : '+') : ''}</td>
        <td>节点内容 {node.id}</td>
      </tr>
    );
    // 若当前节点展开,递归渲染子节点
    if (expandedIds.has(node.id) && node.childrens.length) {
      const childNodes = node.childrens.map(id => flatNodes[id]);
      return [row, ...renderRows(childNodes)];
    }
    return [row];
  });
};

// 切换展开/折叠状态
const toggleExpand = (id) => {
  setExpandedIds(prev => {
    const newSet = new Set(prev);
    if (newSet.has(id)) {
      newSet.delete(id);
      // 可选:递归折叠所有子节点,避免状态混乱
      collapseChildren(id, newSet);
    } else {
      newSet.add(id);
      // 可选:自动展开所有父节点,确保子节点可见
      expandParents(id, newSet);
    }
    return newSet;
  });
};

// 递归折叠子节点的辅助函数
const collapseChildren = (parentId, set) => {
  const node = flatNodes[parentId];
  node.childrens.forEach(childId => {
    set.delete(childId);
    collapseChildren(childId, set);
  });
};

// 递归展开父节点的辅助函数
const expandParents = (childId, set) => {
  const node = flatNodes[childId];
  if (node.parentId !== null) {
    set.add(node.parentId);
    expandParents(node.parentId, set);
  }
};

三、大数据量适配:虚拟滚动

如果存在数千条节点,全量渲染会导致页面卡顿,建议引入虚拟滚动(如react-window),仅渲染当前可视区域内的行,大幅减少DOM节点数量。实现思路:

  1. 提前将所有需渲染的行(含展开子节点)整理为扁平列表(可通过递归遍历树形结构生成,或维护缓存列表)
  2. 用虚拟滚动组件包裹列表,只渲染可视范围内的行

四、维护父子节点状态关联

根据业务需求,可添加状态关联逻辑:

  • 展开父节点时,自动展开所有子节点(或保持子节点原有状态)
  • 展开子节点时,自动将所有父节点标记为展开,避免子节点显示但父节点折叠的矛盾

内容的提问来源于stack exchange,提问作者Данияр Булдаков

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:45:31