TreeSelect 树选择
用于分层数据的下拉树选择。
import { TreeSelect } from 'asterui'import type { TreeDataNode } from 'asterui'基础树选择
从树结构中选择单个值。
Select an item
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const basicTreeData: TreeDataNode[] = [
{
key: 'parent',
title: 'Parent Node',
children: [
{
key: 'child1',
title: 'Child Node 1',
children: [
{ key: 'leaf1', title: 'Leaf 1' },
{ key: 'leaf2', title: 'Leaf 2' },
],
},
{ key: 'child2', title: 'Child Node 2' },
],
},
]
const [value, setValue] = useState<string | undefined>()
return (
<TreeSelect
treeData={basicTreeData}
value={value}
onChange={(val) => setValue(val as string)}
placeholder="Select an item"
/>
)
}
export default App 多选
从树中选择多个值。
Select items
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const categoriesData: TreeDataNode[] = [
{
key: 'electronics',
title: 'Electronics',
children: [
{
key: 'phones',
title: 'Phones',
children: [
{ key: 'iphone', title: 'iPhone' },
{ key: 'samsung', title: 'Samsung' },
{ key: 'pixel', title: 'Pixel' },
],
},
{
key: 'laptops',
title: 'Laptops',
children: [
{ key: 'macbook', title: 'MacBook' },
{ key: 'thinkpad', title: 'ThinkPad' },
],
},
],
},
{
key: 'clothing',
title: 'Clothing',
children: [
{ key: 'shirts', title: 'Shirts' },
{ key: 'pants', title: 'Pants' },
{ key: 'shoes', title: 'Shoes' },
],
},
]
const [value, setValue] = useState<string[]>([])
return (
<TreeSelect
treeData={categoriesData}
value={value}
onChange={(val) => setValue(val as string[])}
placeholder="Select items"
multiple
/>
)
}
export default App 可勾选
使用复选框进行选择,带有父子关联。
Check items
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const categoriesData: TreeDataNode[] = [
{
key: 'electronics',
title: 'Electronics',
children: [
{
key: 'phones',
title: 'Phones',
children: [
{ key: 'iphone', title: 'iPhone' },
{ key: 'samsung', title: 'Samsung' },
{ key: 'pixel', title: 'Pixel' },
],
},
{
key: 'laptops',
title: 'Laptops',
children: [
{ key: 'macbook', title: 'MacBook' },
{ key: 'thinkpad', title: 'ThinkPad' },
],
},
],
},
{
key: 'clothing',
title: 'Clothing',
children: [
{ key: 'shirts', title: 'Shirts' },
{ key: 'pants', title: 'Pants' },
{ key: 'shoes', title: 'Shoes' },
],
},
]
const [value, setValue] = useState<string[]>([])
return (
<TreeSelect
treeData={categoriesData}
value={value}
onChange={(val) => setValue(val as string[])}
placeholder="Check items"
treeCheckable
/>
)
}
export default App 可搜索
使用搜索过滤树节点。
Search and select
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const categoriesData: TreeDataNode[] = [
{
key: 'electronics',
title: 'Electronics',
children: [
{
key: 'phones',
title: 'Phones',
children: [
{ key: 'iphone', title: 'iPhone' },
{ key: 'samsung', title: 'Samsung' },
{ key: 'pixel', title: 'Pixel' },
],
},
{
key: 'laptops',
title: 'Laptops',
children: [
{ key: 'macbook', title: 'MacBook' },
{ key: 'thinkpad', title: 'ThinkPad' },
],
},
],
},
{
key: 'clothing',
title: 'Clothing',
children: [
{ key: 'shirts', title: 'Shirts' },
{ key: 'pants', title: 'Pants' },
{ key: 'shoes', title: 'Shoes' },
],
},
]
const [value, setValue] = useState<string | undefined>()
return (
<TreeSelect
treeData={categoriesData}
value={value}
onChange={(val) => setValue(val as string)}
placeholder="Search and select"
showSearch
/>
)
}
export default App 尺寸
TreeSelect 有各种尺寸。
Extra small
Small
Medium
Large
Extra large
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
function App() {
const simpleData: TreeDataNode[] = [
{ key: 'opt1', title: 'Option 1' },
{ key: 'opt2', title: 'Option 2' },
{ key: 'opt3', title: 'Option 3' },
]
return (
<div className="flex flex-col gap-2">
<TreeSelect treeData={simpleData} size="xs" placeholder="Extra small" />
<TreeSelect treeData={simpleData} size="sm" placeholder="Small" />
<TreeSelect treeData={simpleData} size="md" placeholder="Medium" />
<TreeSelect treeData={simpleData} size="lg" placeholder="Large" />
<TreeSelect treeData={simpleData} size="xl" placeholder="Extra large" />
</div>
)
}
export default App 验证状态
显示错误或警告状态。
Error state
Warning state
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
function App() {
const simpleData: TreeDataNode[] = [
{ key: 'opt1', title: 'Option 1' },
{ key: 'opt2', title: 'Option 2' },
{ key: 'opt3', title: 'Option 3' },
]
return (
<div className="flex flex-col gap-2">
<TreeSelect treeData={simpleData} status="error" placeholder="Error state" />
<TreeSelect treeData={simpleData} status="warning" placeholder="Warning state" />
</div>
)
}
export default App 异步加载
展开时异步加载树节点。
Expand to load
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const [treeData, setTreeData] = useState<TreeDataNode[]>([
{ key: 'region1', title: 'Region 1' },
{ key: 'region2', title: 'Region 2' },
])
const loadData = async (node: TreeDataNode) => {
await new Promise((resolve) => setTimeout(resolve, 1000))
setTreeData((prev) => {
const updateNode = (nodes: TreeDataNode[]): TreeDataNode[] =>
nodes.map((n) =>
n.key === node.key
? {
...n,
children: [
{ key: `${n.key}-1`, title: 'Child 1', isLeaf: true },
{ key: `${n.key}-2`, title: 'Child 2', isLeaf: true },
],
}
: { ...n, children: n.children ? updateNode(n.children) : undefined }
)
return updateNode(prev)
})
}
return (
<TreeSelect
treeData={treeData}
loadData={loadData}
placeholder="Expand to load"
/>
)
}
export default App 最大标签数
限制可见标签的数量。
Select items
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const categoriesData: TreeDataNode[] = [
{
key: 'electronics',
title: 'Electronics',
children: [
{
key: 'phones',
title: 'Phones',
children: [
{ key: 'iphone', title: 'iPhone' },
{ key: 'samsung', title: 'Samsung' },
{ key: 'pixel', title: 'Pixel' },
],
},
{
key: 'laptops',
title: 'Laptops',
children: [
{ key: 'macbook', title: 'MacBook' },
{ key: 'thinkpad', title: 'ThinkPad' },
],
},
],
},
{
key: 'clothing',
title: 'Clothing',
children: [
{ key: 'shirts', title: 'Shirts' },
{ key: 'pants', title: 'Pants' },
{ key: 'shoes', title: 'Shoes' },
],
},
]
const [value, setValue] = useState<string[]>([])
return (
<TreeSelect
treeData={categoriesData}
value={value}
onChange={(val) => setValue(val as string[])}
placeholder="Select items"
treeCheckable
maxTagCount={2}
maxTagPlaceholder={(omitted) => `+${omitted.length} more...`}
/>
)
}
export default App 树连接线
显示树节点之间的连接线。
With tree lines
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
function App() {
const basicTreeData: TreeDataNode[] = [
{
key: 'parent',
title: 'Parent Node',
children: [
{
key: 'child1',
title: 'Child Node 1',
children: [
{ key: 'leaf1', title: 'Leaf 1' },
{ key: 'leaf2', title: 'Leaf 2' },
],
},
{ key: 'child2', title: 'Child Node 2' },
],
},
]
return (
<TreeSelect
treeData={basicTreeData}
placeholder="With tree lines"
treeLine
treeDefaultExpandAll
/>
)
}
export default App 禁用项目
某些树节点可以被禁用。
Select an item
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const [value, setValue] = useState<string | undefined>()
const treeDataWithDisabled: TreeDataNode[] = [
{
key: 'parent',
title: 'Available Parent',
children: [
{ key: 'child1', title: 'Available Child' },
{ key: 'child2', title: 'Disabled Child', disabled: true },
{ key: 'child3', title: 'Another Available' },
],
},
]
return (
<TreeSelect
treeData={treeDataWithDisabled}
value={value}
onChange={(val) => setValue(val as string)}
placeholder="Select an item"
/>
)
}
export default App TreeSelect
Section titled “TreeSelect”| 属性 | 描述 | 类型 | 默认值 |
|---|---|---|---|
treeData | 树数据结构 | TreeDataNode[] | [] |
value | 选定的值 | string | string[] | - |
defaultValue | 默认选定的值 | string | string[] | [] |
onChange | 选择更改时的回调 | (value: string | string[], labels: ReactNode[]) => void | - |
multiple | 允许多选 | boolean | false |
treeCheckable | 显示树节点的复选框 | boolean | false |
treeCheckStrictly | 无父子关联地勾选 | boolean | false |
showCheckedStrategy | 如何显示已勾选项目 | 'SHOW_ALL' | 'SHOW_PARENT' | 'SHOW_CHILD' | 'SHOW_ALL' |
showSearch | 启用搜索功能 | boolean | false |
searchValue | 受控搜索输入值 | string | - |
onSearch | 搜索输入更改时的回调 | (value: string) => void | - |
filterTreeNode | 自定义过滤函数 | (searchValue: string, node: TreeDataNode) => boolean | - |
placeholder | 占位符文本 | string | 'Please select' |
allowClear | 显示清除按钮 | boolean | true |
disabled | 禁用选择 | boolean | false |
size | 输入的大小 | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' |
color | 颜色主题 | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | - |
status | 验证状态 | 'error' | 'warning' | - |
maxTagCount | 要显示的最大标签数 | number | 'responsive' | - |
maxTagPlaceholder | 隐藏标签的内容 | ReactNode | ((omittedValues: string[]) => ReactNode) | - |
treeLine | 显示连接线 | boolean | false |
treeDefaultExpandAll | 默认展开所有树节点 | boolean | false |
treeDefaultExpandedKeys | 默认展开的树节点键 | string[] | [] |
treeExpandedKeys | 受控的已展开树节点键 | string[] | - |
onTreeExpand | 树节点展开/折叠时的回调 | (expandedKeys: string[]) => void | - |
loadData | 异步加载数据 | (node: TreeDataNode) => Promise<void> | - |
fieldNames | 自定义字段名称 | { label?: string; value?: string; children?: string } | - |
open | 受控的下拉菜单可见性 | boolean | - |
onDropdownVisibleChange | 下拉菜单可见性更改时的回调 | (open: boolean) => void | - |
suffixIcon | 自定义后缀图标 | ReactNode | - |
switcherIcon | 自定义展开/折叠图标 | ReactNode | ((props: { expanded: boolean }) => ReactNode) | - |
notFoundContent | 无结果时的内容 | ReactNode | 'No results found' |
dropdownRender | 自定义下拉内容渲染器 | (menu: ReactNode) => ReactNode | - |
popupClassName | 下拉菜单的类 | string | - |
data-testid | 组件的测试 ID | string | 'treeselect' |
className | 额外的 CSS 类 | string | - |
TreeSelect 组件遵循 WAI-ARIA 组合框和树模式,具有正确的 ARIA 属性和键盘导航。
| 键 | 操作 |
|---|---|
| Enter / Space | 打开下拉菜单或选择聚焦的项目 |
| Escape | 关闭下拉菜单 |
| ↓ | 打开下拉菜单或向下移动焦点 |
| ↑ | 向上移动焦点 |
| → | 展开聚焦的树节点 |
| ← | 折叠聚焦的树节点或移至父节点 |
| Home | 将焦点移至第一个项目 |
| End | 将焦点移至最后一个项目 |