> Leaf UI 0.6.0 · Package: @ifhover/leaf-ui · Source: b30c3d3a8fa9c5e15d0d0522cebfbd33f60c6b06
> Browser documentation: https://ifhover.github.io/leaf-ui/v/0.6.0/components/cascader.html

> For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/v/0.6.0/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/v/0.6.0/llms-full.txt.

# Cascader 级联选择

用于逐级选择地区、分类等有层级关系的选项。

## 基础选择

`children` 定义子选项。点击父项展开下一列，点击末级选项确认完整路径；`disabled` 可以禁用一个分支。


项目分类

选择项目分类

默认分类

设计 / 界面设计

禁用分类

请选择

basic.tsx

复制代码

```tsx lineNumbers file="../../src/examples/cascader/basic.tsx"
import { Cascader, Form, FormField } from '@ifhover/leaf-ui';

const options = [
  {
    value: 'design',
    label: '设计',
    children: [
      { value: 'interface', label: '界面设计' },
      { value: 'brand', label: '品牌设计' },
    ],
  },
  {
    value: 'engineering',
    label: '工程',
    children: [
      { value: 'frontend', label: '前端开发' },
      { value: 'backend', label: '后端开发' },
    ],
  },
  { value: 'archived', label: '归档分类', disabled: true },
];

export function CascaderBasic() {
  return (
    <Form layout="vertical">
      <FormField label="项目分类">
        <Cascader aria-label="项目分类" options={options} placeholder="选择项目分类" />
      </FormField>
      <FormField label="默认分类">
        <Cascader aria-label="默认分类" options={options} defaultValue={['design', 'interface']} />
      </FormField>
      <FormField label="禁用分类">
        <Cascader aria-label="禁用分类" options={options} disabled />
      </FormField>
    </Form>
  );
}
```

展开代码

## 受控路径

`value` 是从根节点到末级节点的 value 数组，`onChange` 同时提供完整的选项对象路径。切换父项后会清除旧分支的后续选择。


收货地区

浙江 / 杭州 / 西湖区

选中路径：zhejiang → hangzhou → xihu

controlled.tsx

复制代码

```tsx lineNumbers file="../../src/examples/cascader/controlled.tsx"
import { Cascader, Form, FormField, Text } from '@ifhover/leaf-ui';

import { useState } from 'react';

import { regions } from './options';

export function CascaderControlled() {
  const [value, setValue] = useState<string[]>(['zhejiang', 'hangzhou', 'xihu']);
  return (
    <Form layout="vertical">
      <FormField label="收货地区">
        <Cascader aria-label="收货地区" options={regions} value={value} onChange={setValue} />
      </FormField>
      <Text tone="muted">选中路径：{value.join(' → ') || '未选择'}</Text>
    </Form>
  );
}
```

展开代码

示例使用的地区选项：

```ts title="options.ts" file="../../src/examples/cascader/options.ts"
import type { CascaderOption } from '@ifhover/leaf-ui';

export const regions: CascaderOption[] = [
  {
    value: 'zhejiang',
    label: '浙江',
    children: [
      {
        value: 'hangzhou',
        label: '杭州',
        children: [
          { value: 'xihu', label: '西湖区' },
          { value: 'yuhang', label: '余杭区' },
        ],
      },
      { value: 'ningbo', label: '宁波', children: [{ value: 'haishu', label: '海曙区' }] },
    ],
  },
  {
    value: 'jiangsu',
    label: '江苏',
    children: [
      { value: 'nanjing', label: '南京', children: [{ value: 'gulou', label: '鼓楼区' }] },
      { value: 'suzhou', label: '苏州', children: [{ value: 'gusu', label: '姑苏区' }] },
    ],
  },
  { value: 'archived', label: '归档地区', disabled: true },
];

```

## 搜索、多选与异步加载


搜索、多选与选择中间层

请选择

懒加载与刷新缓存

请选择

刷新数据

capabilities.tsx

复制代码

```tsx lineNumbers file="../../src/examples/cascader/capabilities.tsx"
import type { CascaderOption } from '@ifhover/leaf-ui';

import { Button, Cascader, Flex, Space, Text } from '@ifhover/leaf-ui';

import { useCallback, useState } from 'react';

const options = [
  {
    value: 'product',
    label: 'Product',
    children: [
      { value: 'ui', label: 'UI' },
      { value: 'web', label: 'Web' },
    ],
  },
  { value: 'team', label: 'Team', children: [{ value: 'design', label: 'Design' }] },
];

const lazy: CascaderOption[] = [{ value: 'remote', label: 'Remote', isLeaf: false }];

export function Capabilities() {
  const [version, setVersion] = useState(0);
  const load = useCallback(async (option: CascaderOption, signal: AbortSignal) => {
    await new Promise<void>((resolve, reject) => {
      const timer = setTimeout(resolve, 350);
      signal.addEventListener(
        'abort',
        () => {
          clearTimeout(timer);
          reject(signal.reason);
        },
        { once: true },
      );
    });
    return [{ value: `${option.value}-child`, label: 'Loaded item', isLeaf: true }];
  }, []);
  return (
    <Space direction="vertical" align="stretch">
      <Flex direction="column" gap="sm" align="center">
        <Text>
          {'搜索、多选与选择中间层'}
        </Text>
        <Cascader options={options} showSearch multiple changeOnSelect />
      </Flex>
      <Flex direction="column" gap="sm" align="center">
        <Text>{'懒加载与刷新缓存'}</Text>
        <Cascader options={lazy} loadData={load} cacheKey={version} allowClear />
      </Flex>
      <Button variant="outline" onClick={() => setVersion(version + 1)}>
        {'刷新数据'}
      </Button>
    </Space>
  );
}
```

展开代码

## 单行多选

设置 `tagWrap={false}` 后，已选项始终展示在一行内。长文字自动省略，放不下的选项合并为 `+N`；空间很窄时只显示数量，打开浮层可查看和修改选择。`maxTagCount` 可进一步限制标签数量，`maxTagCount="responsive"` 也会启用单行自动折叠。


产品团队 / 产品体验设计产品团队 / 前端开发产品团队 / 移动端开发+3

single-line.tsx

复制代码

```tsx lineNumbers file="../../src/examples/cascader/single-line.tsx"
import { Cascader } from '@ifhover/leaf-ui';

const options = [
  {
    value: 'product',
    label: '产品团队',
    children: [
      { value: 'design', label: '产品体验设计' },
      { value: 'web', label: '前端开发' },
      { value: 'mobile', label: '移动端开发' },
    ],
  },
];

export function SingleLine() {
  return (
    <Cascader
      aria-label="产品团队"
      multiple
      showSearch
      tagWrap={false}
      options={options}
      defaultValue={[
        ['product', 'design'],
        ['product', 'web'],
        ['product', 'mobile'],
      ]}
    />
  );
}
```

展开代码

## Cascader API

| 属性                  | 类型                                                                                                                                                                                   | 默认值     | 说明                              |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | ------------------------------- |
| `popupPlacement`    | `'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'`                 | —       | 浮层相对触发控件的位置。                    |
| `popupClassName`    | `string`                                                                                                                                                                             | —       | 浮层的自定义类名。                       |
| `popupStyle`        | `CSSProperties`                                                                                                                                                                      | —       | 浮层的自定义样式。                       |
| `popupRender`       | `(content: React.ReactNode) => React.ReactNode`                                                                                                                                      | —       | 包装或补充面板内容，保留传入的内容以维持交互。         |
| `getPopupContainer` | `() => Element \| DocumentFragment`                                                                                                                                                  | —       | 返回浮层的挂载容器，也可返回 ShadowRoot。      |
| `options`           | `readonly `[`CascaderOption`](#cascaderoption)`[]`                                                                                                                                   | 必填      | 必需。层级选项列表                       |
| `size`              | `'sm' \| 'md' \| 'lg'`                                                                                                                                                               | `'md'`  | 选择器尺寸                           |
| `status`            | `'error' \| 'warning'`                                                                                                                                                               | —       | 校验状态                            |
| `placeholder`       | `string`                                                                                                                                                                             | `'请选择'` | 未选择时的提示文字                       |
| `name`              | `string`                                                                                                                                                                             | —       | 字段名 / 关联的表单 ID                  |
| `required`          | `boolean`                                                                                                                                                                            | `false` | 要求整体值非空，复合控件只校验一次。              |
| `allowClear`        | `boolean`                                                                                                                                                                            | `true`  | 清除后返回两个空数组                      |
| `onOpenChange`      | `(open: boolean) => void`                                                                                                                                                            | —       | 面板展开或收起                         |
| `open`              | `boolean`                                                                                                                                                                            | —       | 控制面板是否展开。                       |
| `defaultOpen`       | `boolean`                                                                                                                                                                            | —       | 面板初始展开状态。                       |
| `readOnly`          | `boolean`                                                                                                                                                                            | —       | 锁定业务值，禁止输入、选择、清除和删除。            |
| `showSearch`        | `boolean`                                                                                                                                                                            | —       | 启用搜索输入。                         |
| `changeOnSelect`    | `boolean`                                                                                                                                                                            | —       | 允许选择中间层级。                       |
| `displayRender`     | `(labels: ReactNode[], selectedOptions: `[`CascaderOption`](#cascaderoption)`[]) => ReactNode`                                                                                       | —       | 自定义路径的显示内容。                     |
| `optionRender`      | `(option: `[`CascaderOption`](#cascaderoption)`) => ReactNode`                                                                                                                       | —       | 自定义选项内容。                        |
| `loadData`          | `(option: `[`CascaderOption`](#cascaderoption)`, signal: AbortSignal) => Promise<readonly `[`CascaderOption`](#cascaderoption)`[]>`                                                  | —       | 异步加载子节点；应响应 AbortSignal。        |
| `onLoadError`       | `(error: unknown, option: `[`CascaderOption`](#cascaderoption)`) => void`                                                                                                            | —       | 加载失败时调用，可展示重试提示。                |
| `cacheKey`          | `string \| number`                                                                                                                                                                   | —       | 数据版本改变时清空懒加载缓存，并取消旧请求。          |
| `tagWrap`           | `boolean`                                                                                                                                                                            | `true`  | 允许多选标签换行；false 单行显示并自动折叠溢出项。    |
| `maxTagCount`       | `number \| 'responsive'`                                                                                                                                                             | —       | 最多展示的标签数；responsive 根据可用宽度自动折叠。 |
| `multiple`          | `false \| true`                                                                                                                                                                      | `false` | 启用多选；value 和回调的类型随之变化。          |
| `value`             | `readonly string[] \| readonly (readonly string[])[]`                                                                                                                                | `[]`    | 受控路径 / 非受控初始路径                  |
| `defaultValue`      | `readonly string[] \| readonly (readonly string[])[]`                                                                                                                                | `[]`    | 受控路径 / 非受控初始路径                  |
| `onChange`          | `((value: string[], selectedOptions: `[`CascaderOption`](#cascaderoption)`[]) => void) \| ((value: string[][], selectedOptions: `[`CascaderOption`](#cascaderoption)`[][]) => void)` | —       | 末级选择完成或清除时触发                    |
| `disabled`          | `boolean`                                                                                                                                                                            | `false` | 禁用交互。                           |
| `form`              | `string`                                                                                                                                                                             | —       | 关联的原生表单 ID。                     |
| `ref`               | `Ref<HTMLButtonElement>`                                                                                                                                                             | —       | 触发按钮引用                          |

同一层内的 value 应唯一，传入路径应完整且存在于 options 中。其余原生 button 属性和 `aria-*` 透传至触发按钮；`className` / `style` 作用于外层容器。

## 类型

[`CascaderProps`](#cascader-api) 用于定义组件属性。单独组装层级选项时，可以使用 [`CascaderOption`](#cascaderoption)：

```ts
import type { CascaderProps, CascaderOption, ControlSize, ControlStatus } from '@ifhover/leaf-ui';

const options: CascaderOption[] = [
  {
    label: '浙江',
    value: 'zhejiang',
    children: [{ label: '杭州', value: 'hangzhou' }],
  },
];
```

### CascaderOption

| 属性         | 类型                                             | 默认值     | 说明              |
| ---------- | ---------------------------------------------- | ------- | --------------- |
| `value`    | `string`                                       | 必填      | 选项值，同一层内应唯一     |
| `label`    | `string`                                       | 必填      | 选项文字            |
| `disabled` | `boolean`                                      | `false` | 禁用该选项及其子级       |
| `children` | [`readonly CascaderOption[]`](#cascaderoption) | —       | 子选项；没有子选项时可确认选择 |

## 表单与键盘

设置 `name` 后，FormData 的值为 JSON 数组字符串，例如 `["zhejiang","hangzhou","xihu"]`，清除后为空字符串。可用 JSON.parse 读取路径。非受控组件支持表单 reset，受控组件需同步重置自己的状态。

Enter、空格或 ↓ 打开面板，↑ / ↓ 在列内移动，Home / End 移至首尾，→ 展开子级，← 返回上一级，Enter 选择。Tab 在各列之间移动，离开面板时聚焦表单中的后续控件；Escape 收起并聚焦触发按钮。关闭时未确认的路径不会提交。

面板沿用局部主题，较深层级可以横向滚动查看。为控件提供 label 或 aria-label。

## CascaderOption

| 属性            | 类型                                                 | 默认值 | 说明                    |
| ------------- | -------------------------------------------------- | --- | --------------------- |
| `value`       | `string`                                           | —   | 必需。受控值。               |
| `label`       | `ReactNode`                                        | —   | 必需。展示文字或内容。           |
| `searchLabel` | `string`                                           | —   | 搜索时使用的纯文本。            |
| `isLeaf`      | `boolean`                                          | —   | 明确指定是否为叶子节点，配合异步加载使用。 |
| `disabled`    | `boolean`                                          | —   | 禁用交互。                 |
| `children`    | `readonly `[`CascaderOption`](#cascaderoption)`[]` | —   | 子内容；嵌套数据类型表示子节点。      |

## CascaderFieldNames

| 属性         | 类型       | 默认值 | 说明                    |
| ---------- | -------- | --- | --------------------- |
| `value`    | `string` | —   | 受控值。                  |
| `label`    | `string` | —   | 展示文字或内容。              |
| `children` | `string` | —   | 子内容；嵌套数据类型表示子节点。      |
| `disabled` | `string` | —   | 禁用交互。                 |
| `isLeaf`   | `string` | —   | 明确指定是否为叶子节点，配合异步加载使用。 |
