如何在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
相关产品推荐
相关产品推荐

