跳转到内容

Tree 树形控件

用于显示嵌套数据的分层树结构。

import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'

基础树

带有可展开节点的简单树。

Parent Node
Child Node 1
Leaf Node 1
Leaf Node 2
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  return (
      <Tree treeData={basicTreeData} defaultExpandedKeys={['0', '0-0']} />
    )
}

export default App

可勾选

带有复选框选择的树。

Parent Node
Child Node 1
Leaf Node 1
Leaf Node 2
Child Node 2
Leaf Node 3

Checked: None

import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  const [checkedKeys, setCheckedKeys] = useState<string[]>([])
  
  return (
      <Tree
        treeData={basicTreeData}
        checkable
        checkedKeys={checkedKeys}
        onCheck={setCheckedKeys}
        defaultExpandedKeys={['0', '0-0', '0-1']}
      />
      <p className="mt-4 text-sm">Checked: {checkedKeys.join(', ') || 'None'}</p>
    )
}

export default App

可选择

带有节点选择的树。

Parent Node
Child Node 1
Leaf Node 1
Leaf Node 2
Child Node 2
Leaf Node 3

Selected: None

import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  const [selectedKeys, setSelectedKeys] = useState<string[]>([])
  
  return (
      <Tree
        treeData={basicTreeData}
        selectable
        selectedKeys={selectedKeys}
        onSelect={setSelectedKeys}
        defaultExpandedKeys={['0', '0-0', '0-1']}
      />
      <p className="mt-4 text-sm">Selected: {selectedKeys.join(', ') || 'None'}</p>
    )
}

export default App

多选

允许选择多个节点。

Parent Node
Child Node 1
Leaf Node 1
Leaf Node 2
Child Node 2
Leaf Node 3
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  const [selectedKeys, setSelectedKeys] = useState<string[]>([])
  
  return (
      <Tree
        treeData={basicTreeData}
        selectable
        multiple
        selectedKeys={selectedKeys}
        onSelect={setSelectedKeys}
        defaultExpandedKeys={['0', '0-0', '0-1']}
      />
    )
}

export default App

显示连接线

显示节点之间的连接线。

src
components
Button.tsx
Input.tsx
App.tsx
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'

function App() {
  const fileTreeData: TreeDataNode[] = [
    {
      key: 'src',
      title: 'src',
      children: [
        {
          key: 'components',
          title: 'components',
          children: [
            { key: 'Button.tsx', title: 'Button.tsx' },
            { key: 'Input.tsx', title: 'Input.tsx' },
          ],
        },
        { key: 'App.tsx', title: 'App.tsx' },
      ],
    },
  ]
  
  return (
      <Tree
        treeData={fileTreeData}
        showLine
        defaultExpandedKeys={['src', 'components']}
      />
    )
}

export default App

显示图标

显示节点的自定义图标。

src
App.tsx
index.tsx
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { FolderIcon, DocumentIcon } from '@aster-ui/icons/solid'

function App() {
  const treeDataWithIcons: TreeDataNode[] = [
    {
      key: 'src',
      title: 'src',
      icon: <FolderIcon size="sm" />,
      children: [
        { key: 'App.tsx', title: 'App.tsx', icon: <DocumentIcon size="sm" /> },
        { key: 'index.tsx', title: 'index.tsx', icon: <DocumentIcon size="sm" /> },
      ],
    },
  ]
  
  return (
      <Tree treeData={treeDataWithIcons} showIcon defaultExpandedKeys={['src']} />
    )
}

export default App

复合模式

使用 Tree.Node 进行声明式树结构。

Parent Node
Child Node 2
import { Tree } from 'asterui'

function App() {
  return (
      <Tree defaultExpandedKeys={['parent']}>
        <Tree.Node key="parent" title="Parent Node">
          <Tree.Node key="child-1" title="Child Node 1">
            <Tree.Node key="leaf-1" title="Leaf Node 1" />
            <Tree.Node key="leaf-2" title="Leaf Node 2" />
          </Tree.Node>
          <Tree.Node key="child-2" title="Child Node 2" />
        </Tree.Node>
      </Tree>
    )
}

export default App

复选框颜色

使用 DaisyUI 颜色自定义复选框外观。

Parent Node
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  return (
      <Tree
        treeData={basicTreeData}
        checkable
        checkboxColor="success"
        checkboxSize="md"
        defaultExpandedKeys={['0']}
      />
    )
}

export default App

严格勾选

解耦父子复选框关系。

Parent Node
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  const [checkedKeys, setCheckedKeys] = useState<string[]>([])
  
  return (
      <Tree
        treeData={basicTreeData}
        checkable
        checkStrictly
        checkedKeys={checkedKeys}
        onCheck={setCheckedKeys}
        defaultExpandedKeys={['0']}
      />
    )
}

export default App

异步加载

展开时异步加载子节点。

Expand to load
Expand to load
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const [treeData, setTreeData] = useState<TreeDataNode[]>([
    { key: '0', title: 'Expand to load' },
    { key: '1', title: 'Expand to load' },
  ])
  
  const loadData = async (node: TreeDataNode) => {
    await new Promise(resolve => setTimeout(resolve, 1000))
    setTreeData(prev => {
      const update = (nodes: TreeDataNode[]): TreeDataNode[] =>
        nodes.map(n => n.key === node.key
          ? { ...n, children: [
              { key: `${n.key}-0`, title: 'Child 1', isLeaf: true },
              { key: `${n.key}-1`, title: 'Child 2', isLeaf: true },
            ]}
          : { ...n, children: n.children ? update(n.children) : undefined }
        )
      return update(prev)
    })
  }
  
  return (
      <Tree treeData={treeData} loadData={loadData} />
    )
}

export default App
属性描述类型默认值
treeData树数据结构(复合模式的替代)TreeDataNode[][]
children复合模式的 Tree.Node 子元素React.ReactNode-
checkable为每个节点显示复选框booleanfalse
checkboxColor复选框颜色(DaisyUI)'primary' | 'secondary' | 'accent' | 'neutral' | 'info' | 'success' | 'warning' | 'error''primary'
checkboxSize复选框大小(DaisyUI)'xs' | 'sm' | 'md' | 'lg' | 'xl''sm'
checkedKeys受控的已勾选键string[]-
defaultCheckedKeys默认已勾选键string[][]
checkStrictly解耦父子复选框关系booleanfalse
onCheck节点勾选时的回调(keys: string[], info: { node, checked }) => void-
selectable启用节点选择booleantrue
selectedKeys受控的已选择键string[]-
defaultSelectedKeys默认已选择键string[][]
onSelect节点选择时的回调(keys: string[], info: { node, selected }) => void-
multiple允许多选booleanfalse
expandedKeys受控的已展开键string[]-
defaultExpandedKeys默认已展开键string[][]
defaultExpandAll默认展开所有节点booleanfalse
autoExpandParent自动展开父节点booleantrue
onExpand节点展开时的回调(keys: string[], info: { node, expanded }) => void-
showLine显示连接线booleanfalse
showIcon显示节点图标booleanfalse
blockNode使节点填充水平空间booleanfalse
switcherIcon自定义展开/折叠图标ReactNode | ((expanded: boolean) => ReactNode)-
titleRender自定义标题渲染函数(node: TreeDataNode) => ReactNode-
filterTreeNode过滤函数以高亮节点(node: TreeDataNode) => boolean-
loadData异步数据加载函数(node: TreeDataNode) => Promise<void>-
onRightClick右键点击处理程序(info: { event, node }) => void-
fieldNames数据映射的自定义字段名称{ key?: string; title?: string; children?: string }-
className额外的 CSS 类string-

Tree 组件实现完整的 WAI-ARIA 树模式:

  • 容器上使用 role="tree",节点上使用 role="treeitem"
  • aria-expanded 指示节点展开状态
  • aria-selected 指示选择状态
  • aria-checked 指示复选框状态(带有不确定的 "mixed")
  • aria-disabled 指示禁用状态
  • aria-level 指示嵌套深度
操作
将焦点移至下一个可见节点
将焦点移至上一个可见节点
展开折叠的节点,或移至第一个子节点
折叠展开的节点
Enter / Space切换复选框、选择节点或展开/折叠
Home将焦点移至第一个节点
End将焦点移至最后一个可见节点