首页 > 解决方案 > Material UI Tree View,检查我点击的节点是否有子节点

问题描述

所以我尝试使用 Material UI ( https://material-ui.com/components/tree-view/ ) 中的树视图创建一棵树。我们可以从他们的页面中获取示例:

const data = {
  id: 'root',
  name: 'Parent',
  children: [
    {
      id: '1',
      name: 'Child - 1',
    },
    {
      id: '3',
      name: 'Child - 3',
      children: [
        {
          id: '4',
          name: 'Child - 4',
        },
      ],
    },
  ],
};

const useStyles = makeStyles({
  root: {
    height: 110,
    flexGrow: 1,
    maxWidth: 400,
  },
});

export default function RecursiveTreeView() {
  const classes = useStyles();

  const renderTree = (nodes) => (
    <TreeItem key={nodes.id} nodeId={nodes.id} label={nodes.name}>
      {Array.isArray(nodes.children) ? nodes.children.map((node) => renderTree(node)) : null}
    </TreeItem>
  );

  return (
    <TreeView
      className={classes.root}
      defaultCollapseIcon={<ExpandMoreIcon />}
      defaultExpanded={['root']}
      defaultExpandIcon={<ChevronRightIcon />}
    >
      {renderTree(data)}
    </TreeView>
  );
}

我想要做的是,每当我点击一个节点时,只有当它是一个叶节点时才会触发一些功能。树视图的“onNodeSelect”道具只给了我节点ID,而不是关于节点的任何其他信息。我知道一种方法是在原始 json 中搜索该 id 并找到该节点,然后检查它是否有子节点,但我的 json 很大,我不想这样做。还有什么办法吗?

标签: reactjsmaterial-uitreeview

解决方案


您可能会使用 TreeItem 组件的 onLabelClick 并放弃树视图的“选择”部分(例如,在 TreeView 上使用 disableSelection)。

那么你的代码可能会变成

const handleTreeItemClick = (node) => {
  if( node.children && node.children.length ) {
    // do some stuff
  } else {
    // do something else
  }  
}

const renderTree = (nodes) => (
  <TreeItem
    key={nodes.id}
    nodeId={nodes.id}
    label={nodes.name}
    onLabelClick={() => handleTreeItemClick(nodes)}
  >
    {Array.isArray(nodes.children) ? nodes.children.map((node) => renderTree(node)) : null}
  </TreeItem>
);

否则,您可能能够使用指向数据节点的 id 对数据进行哈希处理(不确定对大型 json 对象进行哈希处理的性能?),然后只需从哈希中查找值,而不是每次都搜索。烦人我知道例如

// do this outside of the render, perhaps in a redux selector or reducer
const hashMethod = (nodes, hash = {}) => {
  return nodes.reduce((h, node) => {
    h[node.id] = node;
    if( node.children) {
      h = hashMethod(node.children, h);
    }  
    return h;
  }, hash);
}

// sorry turned it into an array first so I can use reduce easier
const hashedData = hashMethod([data]); 

然后在组件内的 onNodeSelect 处理程序中(用于单个选择)

const handleNodeSelect = (nodeId) => {
  const node = hashedData(nodeId);
  // do what you need with the data
}

推荐阅读