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

如何在MUI v5的RichTreeView中暴露自定义Item属性?

在MUI RichTreeView的自定义TreeItem中获取自定义属性

问题背景

使用MUI RichTreeView时,自定义TreeItem组件无法直接获取到数据项中的自定义属性(如customProperty1、customProperty2),打印props仅能看到id、label等默认字段;尝试通过ITEMS.find()查找对应项获取属性,但担心大数据集下的性能问题。

解决方案

方法1:通过getItemProps传递自定义属性

RichTreeView提供了getItemProps属性,可在渲染每个节点时,将当前item的自定义属性直接注入到自定义TreeItem的props中,无需额外查找:

// 调整RichTreeView的配置
<RichTreeView
  aria-label="icon expansion"
  sx={{ position: 'relative' }}
  items={ITEMS}
  slots={{ item: CustomTreeItem }}
  // 传递自定义属性到TreeItem组件
  getItemProps={(item) => ({
    customProperty1: item.customProperty1,
    customProperty2: item.customProperty2
  })}
/>

// 在CustomTreeItem中直接获取
const CustomTreeItem = forwardRef((props, ref) => {
  // 解构出传递的自定义属性
  const { id, itemId, label, disabled, children, customProperty1, customProperty2, ...other } = props;

  // 直接使用自定义属性
  console.log('customProperty1:', customProperty1);
  console.log('customProperty2:', customProperty2);

  const { getRootProps, getContentProps, getIconContainerProps, getLabelProps, getGroupTransitionProps, status } = useTreeItem2({
    id,
    itemId,
    children,
    label,
    disabled,
    rootRef: ref,
  });

  return (
    <TreeItem2Provider itemId={itemId}>
      <TreeItem2Root {...getRootProps(other)}>
        <CustomTreeItemContent {...getContentProps()}>
          <Box sx={{ flexGrow: 1 }}>
            <Stack direction="row" alignItems="center">
              <TreeItem2IconContainer {...getIconContainerProps()}>
                <TreeItem2Icon status={status} />
              </TreeItem2IconContainer>
              <TreeItem2Label {...getLabelProps()} />
            </Stack>
            {!children && (
              <Stack direction="row" justifyContent="flex-start" sx={{ pl: 2, ml: 2, mt: 1, backgroundColor: '#2F3B5F', borderRadius: 10, px: 2, my: 1 }}>
                All spare parts (xxxxx)
                <Stack sx={{ ml: 'auto' }}>(folder icon here)</Stack>
              </Stack>
            )}
          </Box>
        </CustomTreeItemContent>
        {children && <TreeItem2GroupTransition {...getGroupTransitionProps()} />}
      </TreeItem2Root>
    </TreeItem2Provider>
  );
});

方法2:优化查找性能(适合无法使用getItemProps的场景)

如果必须通过itemId查找对应项,将数组转换为Map结构可将查找时间复杂度从O(n)降到O(1),避免大数据集下的性能损耗:

import { useMemo } from 'react';

// 提前将ITEMS转换为Map(放在组件外部或用useMemo缓存)
const itemMap = useMemo(() => new Map(ITEMS.map(item => [item.id, item])), [ITEMS]);

// 在CustomTreeItem中使用
const CustomTreeItem = forwardRef((props, ref) => {
  const { id, itemId, label, disabled, children, ...other } = props;
  
  // 通过Map快速获取完整item对象
  const currentItem = itemMap.get(itemId);
  const customProperty1 = currentItem?.customProperty1;
  const customProperty2 = currentItem?.customProperty2;

  console.log('customProperty1:', customProperty1);
  console.log('customProperty2:', customProperty2);

  const { getRootProps, getContentProps, getIconContainerProps, getLabelProps, getGroupTransitionProps, status } = useTreeItem2({
    id,
    itemId,
    children,
    label,
    disabled,
    rootRef: ref,
  });

  return (
    <TreeItem2Provider itemId={itemId}>
      <TreeItem2Root {...getRootProps(other)}>
        <CustomTreeItemContent {...getContentProps()}>
          <Box sx={{ flexGrow: 1 }}>
            <Stack direction="row" alignItems="center">
              <TreeItem2IconContainer {...getIconContainerProps()}>
                <TreeItem2Icon status={status} />
              </TreeItem2IconContainer>
              <TreeItem2Label {...getLabelProps()} />
            </Stack>
            {!children && (
              <Stack direction="row" justifyContent="flex-start" sx={{ pl: 2, ml: 2, mt: 1, backgroundColor: '#2F3B5F', borderRadius: 10, px: 2, my: 1 }}>
                All spare parts (xxxxx)
                <Stack sx={{ ml: 'auto' }}>(folder icon here)</Stack>
              </Stack>
            )}
          </Box>
        </CustomTreeItemContent>
        {children && <TreeItem2GroupTransition {...getGroupTransitionProps()} />}
      </TreeItem2Root>
    </TreeItem2Provider>
  );
});

方法3:通过useTreeItem2Context获取完整item

MUI的TreeItem2提供了上下文,可直接获取当前节点的完整item对象:

import { useTreeItem2Context } from '@mui/x-tree-view';

const CustomTreeItem = forwardRef((props, ref) => {
  const { id, itemId, label, disabled, children, ...other } = props;
  
  // 从上下文中获取完整item
  const { item } = useTreeItem2Context();
  const customProperty1 = item?.customProperty1;
  const customProperty2 = item?.customProperty2;

  console.log('customProperty1:', customProperty1);
  console.log('customProperty2:', customProperty2);

  const { getRootProps, getContentProps, getIconContainerProps, getLabelProps, getGroupTransitionProps, status } = useTreeItem2({
    id,
    itemId,
    children,
    label,
    disabled,
    rootRef: ref,
  });

  return (
    <TreeItem2Provider itemId={itemId}>
      <TreeItem2Root {...getRootProps(other)}>
        <CustomTreeItemContent {...getContentProps()}>
          <Box sx={{ flexGrow: 1 }}>
            <Stack direction="row" alignItems="center">
              <TreeItem2IconContainer {...getIconContainerProps()}>
                <TreeItem2Icon status={status} />
              </TreeItem2IconContainer>
              <TreeItem2Label {...getLabelProps()} />
            </Stack>
            {!children && (
              <Stack direction="row" justifyContent="flex-start" sx={{ pl: 2, ml: 2, mt: 1, backgroundColor: '#2F3B5F', borderRadius: 10, px: 2, my: 1 }}>
                All spare parts (xxxxx)
                <Stack sx={{ ml: 'auto' }}>(folder icon here)</Stack>
              </Stack>
            )}
          </Box>
        </CustomTreeItemContent>
        {children && <TreeItem2GroupTransition {...getGroupTransitionProps()} />}
      </TreeItem2Root>
    </TreeItem2Provider>
  );
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 04:20:21