跳到内容
+

从 v6 迁移到 v7

本指南介绍了将树形视图从 v6 迁移到 v7 所需的更改。

简介

这是将 @mui/x-tree-view 从 v6 升级到 v7 的参考指南。要了解有关新主要版本更改的更多信息,请查看 关于 MUI X v7 发布的博客文章

开始使用新版本

package.json 中,将树形视图包的版本更改为 ^7.0.0

-"@mui/x-tree-view": "^6.0.0",
+"@mui/x-tree-view": "^7.0.0",

更新 @mui/material

为了可以选择使用来自 @mui/material 的最新 API,软件包的对等依赖版本已更新至 ^5.15.14。这只是次要版本更改,因此不应引起任何重大更改。请将您的 @mui/material 包更新到此版本或更高版本。

运行代码转换

preset-safe 代码转换将自动调整您的大部分代码,以适应 v7 中的重大更改。您可以运行 v7.0.0/tree-view/preset-safe 仅针对树形视图,或运行 v7.0.0/preset-safe 以同时针对其他 MUI X 组件,如数据表格。

在选择 <path> 参数时,您可以针对特定文件、文件夹或整个代码库运行它。

// Tree View specific
npx @mui/x-codemod@latest v7.0.0/tree-view/preset-safe <path>

// Target other MUI X components as well
npx @mui/x-codemod@latest v7.0.0/preset-safe <path>

preset-safe 代码转换处理的重大更改在屏幕右侧的目录中或在其处理的具体点旁边用 ✅ 表情符号表示。

如果您已经应用了 v7.0.0/tree-view/preset-safe (或 v7.0.0/preset-safe) 代码转换,则您应该无需对这些项目采取任何进一步操作。如果重大更改的特定部分不是代码转换的一部分或需要一些手动工作,它将在每个部分的末尾列出。

所有其他更改必须手动处理。

重大更改

由于 v7 是一个主要版本,因此它包含影响公共 API 的更改。这些更改是为了保持一致性、提高稳定性和为新功能腾出空间而进行的。

删除旧版捆绑包

所有 MUI X 包中已删除对 IE 11 的支持。不再包含用于支持旧浏览器(如 IE 11)的 legacy 捆绑包。

放弃 Webpack 4 支持

放弃对旧浏览器的支持也意味着我们不再转换现代浏览器原生支持的某些功能 – 例如 Nullish CoalescingOptional Chaining

Webpack 4 不支持这些功能,因此如果您正在使用 Webpack 4,您将需要自己转换这些功能或升级到 Webpack 5。

以下是如何在 Webpack 4 上使用 @babel/preset-env preset 转换这些功能的示例

 // webpack.config.js

 module.exports = (env) => ({
   // ...
   module: {
     rules: [
       {
         test: /\.[jt]sx?$/,
-        exclude: /node_modules/,
+        exclude: [
+          {
+            test: path.resolve(__dirname, 'node_modules'),
+            exclude: [path.resolve(__dirname, 'node_modules/@mui/x-tree-view')],
+          },
+        ],
       },
     ],
   },
 });

✅ 将 nodeId 重命名为 itemId

为了保持一致性,树形项目使用的必需 nodeId prop 已重命名为 itemId

 <TreeView>
-  <TreeItem label="Item 1" nodeId="one">
+  <TreeItem label="Item 1" itemId="one">
 </TreeView>

相同的更改已应用于 ContentComponent prop

 const CustomContent = React.forwardRef((props, ref) => {
-  const id = props.nodeId;
+  const id = props.itemId;
   // Render some UI
 });

 function App() {
   return (
     <SimpleTreeView>
       <TreeItem ContentComponent={CustomContent} />
     </SimpleTreeView>
   )
 }

✅ 使用 Simple Tree View 而不是 Tree View

<TreeView /> 组件已被弃用,将在下一个主要版本中删除。您可以开始用新的 <SimpleTreeView /> 组件替换它,该组件具有完全相同的 API

-import { TreeView } from '@mui/x-tree-view';
+import { SimpleTreeView } from '@mui/x-tree-view';

-import { TreeView } from '@mui/x-tree-view/TreeView';
+import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';

   return (
-    <TreeView>
+    <SimpleTreeView>
       <TreeItem itemId="1" label="First item" />
-    </TreeView>
+    </SimpleTreeView>
   );

如果您正在使用主题增强,您还需要迁移它

 const theme = createTheme({
   components: {
-    MuiTreeView: {
+    MuiSimpleTreeView: {
       styleOverrides: {
         root: {
           opacity: 0.5,
         },
       },
     },
   },
 });

如果您正在使用 treeViewClasses 对象,您可以将其替换为新的 simpleTreeViewClasses 对象

 import { treeViewClasses } from '@mui/x-tree-view/TreeView';
 import { simpleTreeViewClasses } from '@mui/x-tree-view/SimpleTreeView';

-const rootClass = treeViewClasses.root;
+const rootClass = simpleTreeViewClasses.root;

使用插槽定义项目图标

定义 expandIcon

用于展开项目子项的图标(在此项目折叠时呈现)现在在 <TreeView /><TreeItem /> 组件上都定义为插槽。

如果您正在使用来自 @mui/icons-materialChevronRight 图标,您可以停止将其传递给您的组件,因为它现在是默认值

-import ChevronRightIcon from '@mui/icons-material/ChevronRight';

 <SimpleTreeView
-  defaultExpandIcon={<ChevronRightIcon />}
 >
   {items}
 </SimpleTreeView>

如果您正在将另一个图标传递给您的 Tree View 组件,您需要在该组件上使用新的 expandIcon 插槽

 <SimpleTreeView
-  defaultExpandIcon={<MyCustomExpandIcon />}
+  slots={{ expandIcon: MyCustomExpandIcon }}
 >
   {items}
 </SimpleTreeView>

如果您正在将另一个图标传递给您的 <TreeItem /> 组件,您需要在该组件上使用新的 expandIcon 插槽

  <SimpleTreeView>
    <TreeItem
      itemId="1"
      label="Item 1"
-     expandIcon={<MyCustomExpandIcon />}
+     slots={{ expandIcon: MyCustomExpandIcon }}
    />
  </SimpleTreeView>

定义 collapseIcon

用于折叠项目子项的图标(在此项目展开时呈现)现在在 <TreeView /><TreeItem /> 组件上都定义为插槽。

如果您正在使用来自 @mui/icons-materialExpandMore 图标,您可以停止将其传递给您的组件,因为它现在是默认值

- import ExpandMoreIcon from '@mui/icons-material/ExpandMore';

  <SimpleTreeView
-   defaultCollapseIcon={<ExpandMoreIcon />}
  >
    {items}
  </SimpleTreeView>

如果您正在将另一个图标传递给您的 Tree View 组件,您需要在该组件上使用新的 collapseIcon 插槽

  <SimpleTreeView
-   defaultCollapseIcon={<MyCustomCollapseIcon />}
+   slots={{ collapseIcon: MyCustomCollapseIcon }}
  >
    {items}
  </SimpleTreeView>

如果您正在将另一个图标传递给您的 <TreeItem /> 组件,您需要在该组件上使用新的 collapseIcon 插槽

  <SimpleTreeView>
    <TreeItem
      itemId="1"
      label="Item 1"
-     collapseIcon={<MyCustomCollapseIcon />}
+     slots={{ collapseIcon: MyCustomCollapseIcon }}
    />
  </SimpleTreeView>

替换 parentIcon

parentIcon prop 已从 Tree View 组件中删除。

如果您正在将一个图标传递给您的 Tree View 组件,您可以通过将相同的图标传递给该组件上的 collapseIconexpandIcon 插槽来实现相同的行为

  <SimpleTreeView
-   defaultParentIcon={<MyCustomParentIcon />}
+   slots={{ collapseIcon: MyCustomParentIcon, expandIcon: MyCustomParentIcon }}
  >
    {items}
  </SimpleTreeView>

定义 endIcon

在没有子项的项目旁边呈现的图标现在在 <TreeView /><TreeItem /> 组件上都定义为插槽。

如果您正在将一个图标传递给您的 Tree View 组件,您需要在该组件上使用新的 endIcon 插槽

  <SimpleTreeView
-   defaultEndIcon={<MyCustomEndIcon />}
+   slots={{ endIcon: MyCustomEndIcon }}
  >
    {items}
  </SimpleTreeView>

如果您正在将一个图标传递给您的 <TreeItem /> 组件,您需要在该组件上使用新的 endIcon 插槽

  <SimpleTreeView>
    <TreeItem
      itemId="1"
      label="Item 1"
-     endIcon={<MyCustomEndIcon />}
+     slots={{ endIcon: MyCustomEndIcon }}
    />
  </SimpleTreeView>

定义 icon

在项目旁边呈现的图标现在在 <TreeItem /> 组件上定义为插槽。

如果您正在将一个图标传递给您的 <TreeItem /> 组件,您需要在该组件上使用新的 icon 插槽

  <SimpleTreeView>
    <TreeItem
      itemId="1"
      label="Item 1"
-     icon={<MyCustomIcon />}
+     slots={{ icon: MyCustomIcon }}
    />
  </SimpleTreeView>

✅ 使用插槽定义组过渡

用于动画项目子项的组件现在在 <TreeItem /> 组件上定义为插槽。

如果您正在将 TransitionComponentTransitionProps 传递给您的 <TreeItem /> 组件,您需要在该组件上使用新的 groupTransition 插槽

 <SimpleTreeView>
   <TreeItem
     itemId="1"
     label="Item 1"
-    TransitionComponent={Fade}
-    TransitionProps={{ timeout: 600 }}
+    slots={{ groupTransition: Fade }}
+    slotProps={{ groupTransition: { timeout: 600 } }}
   />
 </SimpleTreeView>

重命名树形项目组件的 group

<TreeItem /> 组件的 group 类已重命名为 groupTransition,以与其新的插槽名称匹配。

 const StyledTreeItem = styled(TreeItem)({
-  [`& .${treeItemClasses.group}`]: {
+  [`& .${treeItemClasses.groupTransition}`]: {
    marginLeft: 20,
  },
 });

✅ 重命名 onNodeToggleexpandeddefaultExpanded

扩展 props 已被重命名以更好地描述其行为

旧名称 新名称
onNodeToggle onExpandedItemsChange
expanded expandedItems
defaultExpanded defaultExpandedItems
 <TreeView
-  onNodeToggle={handleExpansionChange}
+  onExpandedItemsChange={handleExpansionChange}

-  expanded={expandedItems}
+  expandedItems={expandedItems}

-  defaultExpanded={defaultExpandedItems}
+  defaultExpandedItems={defaultExpandedItems}
 />

✅ 重命名 onNodeSelectselecteddefaultSelected

选择 props 已被重命名以更好地描述其行为

旧名称 新名称
onNodeSelect onSelectedItemsChange
selected selectedItems
defaultSelected defaultSelectedItems
 <TreeView
-  onNodeSelect={handleSelectionChange}
+  onSelectedItemsChange={handleSelectionChange}

-  selected={selectedItems}
+  selectedItems={selectedItems}

-  defaultSelected={defaultSelectedItems}
+  defaultSelectedItems={defaultSelectedItems}
 />

聚焦树形项目而不是树形视图

焦点现在应用于树形项目根元素,而不是树形视图根元素。

此更改将允许需要焦点位于树形项目上的新功能,例如项目的拖放重新排序。它还解决了焦点管理的几个问题,例如当渲染大量项目时无法滚动到聚焦项目。

这主要会影响您编写测试以与树形视图交互的方式

例如,如果您正在使用 react-testing-library 编写测试,以下是更改可能的样子

 it('test example on first item', () => {
   const { getByRole } = render(
     <SimpleTreeView>
       <TreeItem itemId="one" id="one">One</TreeItem>
       <TreeItem itemId="two" id="two">Two</TreeItem>
    </SimpleTreeView>
   );

   // Set the focus to the item "One"
-  const tree = getByRole('tree');
+  const treeItem = getByRole('treeitem', { name: 'One' });
   act(() => {
-    tree.focus();
+    treeItem.focus();
   });
-  fireEvent.keyDown(tree, { key: 'ArrowDown' });
+  fireEvent.keyDown(treeItem, { key: 'ArrowDown' });

  // Check if the new focused item is "Two"
- expect(tree)to.have.attribute('aria-activedescendant', 'two');
+ expect(document.activeElement).to.have.attribute('id', 'two');
 })

✅ 使用 useTreeItemState 而不是 useTreeItem

useTreeItem hook 已重命名为 useTreeItemState。这将有助于基于未来的 useTreeItem hook 创建树形项目组件的新 headless 版本。

-import { TreeItem, useTreeItem } from '@mui/x-tree-view/TreeItem';
+import { TreeItem, useTreeItemState } from '@mui/x-tree-view/TreeItem';

 const CustomContent = React.forwardRef((props, ref) => {
-  const { disabled } = useTreeItem(props.itemId);
+  const { disabled } = useTreeItemState(props.itemId);

   // Render some UI
 });

 function App() {
   return (
     <SimpleTreeView>
       <TreeItem ContentComponent={CustomContent} />
     </SimpleTreeView>
   )
 }

✅ 重命名 onNodeFocus

为了保持一致性,onNodeFocus 回调已重命名为 onItemFocus

 <SimpleTreeView
-  onNodeFocus={onNodeFocus}
+  onItemFocus={onItemFocus}
 />