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

Material-ui TreeView 性能优化:避免未变更子树重复渲染

Material-UI TreeView 大型宽树性能优化方案

核心实现逻辑

利用不可变数据的引用不变特性,配合React.memo的浅比较跳过未变更子树的渲染,从根本上减少全量重渲染的开销。

具体落地步骤

  • 数据源层使用不可变更新规则
    每次修改节点(增删、改属性、改状态)时,仅重新生成「根节点到被修改节点」路径上的节点对象,其余未修改子树的节点直接复用原有对象引用。比如给示例中的F节点添加子节点X时,仅需要重新生成A、C、F、X四个节点,B、D、E节点完全复用原引用,无需任何改动。
    如果不想手动写递归更新逻辑,可以使用Immer库,其produce方法生成的新数据天然符合不可变更新的特性,未改动的节点引用会保持不变。
  • 封装带渲染缓存的自定义TreeItem组件
    MUI原生TreeItem没有做渲染跳过的优化,父组件重渲染时会触发所有子节点的重渲染。你可以用React.memo封装自定义TreeItem,自定义比较函数仅校验核心渲染属性,无变更时直接跳过渲染:
import { TreeItem as MuiTreeItem } from '@mui/lab';
import { memo } from 'react';

const arePropsEqual = (prev, next) => {
  return (
    prev.nodeId === next.nodeId &&
    prev.label === next.label &&
    prev.selected === next.selected &&
    prev.expanded === next.expanded &&
    // 子节点引用不变则无需向下渲染
    prev.children === next.children
  );
};

const TreeItem = memo(({ node, ...rest }) => {
  return <MuiTreeItem nodeId={node.id} label={node.label} {...rest} />;
}, arePropsEqual);
  • 递归渲染逻辑直接复用节点引用
    写树的递归渲染函数时,直接传入原节点对象即可,未修改的节点因为引用不变,会被memo直接跳过渲染:
const renderTreeNode = (node) => {
  return (
    <TreeItem key={node.id} node={node}>
      {node.children?.map(renderTreeNode) ?? null}
    </TreeItem>
  );
};
  • 超大量级节点补充虚拟滚动
    如果节点总数超过1万,仅靠不可变数据优化仍然可能有性能压力,可以搭配虚拟滚动方案,仅渲染可视区域内的节点,无论总节点数多少,单次渲染的节点数始终维持在几十的量级,渲染耗时基本可以稳定在10ms以内。

优化效果

千级节点的常规修改操作(增删节点、切换状态等)的渲染耗时基本可以控制在20ms以内,完全满足性能要求。

内容的提问来源于stack exchange,提问作者jonenst

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 20:27:04