Skip to content

Cascader

Cascader 是多级联动选择器,适合省市区、组织层级、类目路径、区域树等“先选父级,再选子级”的场景。
组件默认以“路径数组”作为值模型,内置受控/非受控、清除、懒加载、changeOnSelect、自定义选项渲染与可访问性支持。

Basic

最小用法只需要传入 optionsvalue 的形态是路径数组,例如 ["zhejiang", "hangzhou"]

常见场景

受控路径

当业务需要联动表单、回填草稿或在提交前统一校验时,使用 value / onValueChange 管理路径数组。

选中即提交中间层

开启 changeOnSelect 后,选择非叶子节点也会立即提交当前路径,适合“选到某一层就足够”的场景。

懒加载与自定义渲染

loadData 用于按需加载子节点,renderOptiondisplayRender 可分别控制面板行与触发器文本。

Usage

基础用法

tsx
import { Cascader } from "@ldkj/web-ui";

const options = [
  {
    label: "浙江",
    value: "zhejiang",
    children: [
      { label: "杭州", value: "hangzhou" },
      { label: "宁波", value: "ningbo" },
    ],
  },
  {
    label: "江苏",
    value: "jiangsu",
    children: [
      { label: "南京", value: "nanjing" },
      { label: "苏州", value: "suzhou" },
    ],
  },
];

export function Example() {
  return (
    <Cascader
      options={options}
      placeholder="请选择地区"
      clearable
    />
  );
}

受控用法

tsx
import * as React from "react";
import { Cascader } from "@ldkj/web-ui";

export function ControlledExample() {
  const [value, setValue] = React.useState<string[]>([]);

  return (
    <Cascader
      options={options}
      value={value}
      onValueChange={setValue}
      placeholder="请选择组织路径"
      clearable
    />
  );
}

懒加载用法

tsx
import * as React from "react";
import { Cascader, type CascaderOption } from "@ldkj/web-ui";

export function LazyExample() {
  const [options, setOptions] = React.useState<CascaderOption[]>([
    { label: "亚洲", value: "asia", isLeaf: false },
    { label: "欧洲", value: "europe", isLeaf: false },
  ]);

  const loadData = async (selectedOptions: CascaderOption[]) => {
    const target = selectedOptions[selectedOptions.length - 1];
    if (!target?.value) return;

    const children =
      target.value === "asia"
        ? [
            { label: "中国", value: "china" },
            { label: "日本", value: "japan" },
          ]
        : [
            { label: "法国", value: "france" },
            { label: "德国", value: "germany" },
          ];

    setOptions((current) =>
      current.map((item) =>
        item.value === target.value ? { ...item, children } : item,
      ),
    );
  };

  return <Cascader options={options} loadData={loadData} placeholder="点击加载" />;
}

API

Cascader

属性说明类型默认值
options级联选项数据CascaderOption[][]
value受控路径值string[]-
defaultValue非受控初始路径值string[][]
onValueChange路径变化回调(value: string[], meta: CascaderValueChangeMeta) => void-
open受控展开状态boolean-
defaultOpen非受控初始展开状态booleanfalse
onOpenChange展开状态变化回调(open: boolean) => void-
placeholder未选择时的占位文案React.ReactNode请选择
separator默认路径分隔符React.ReactNode/
displayRender自定义触发器显示内容(labels, options) => React.ReactNode-
renderOption自定义面板选项渲染(option, state) => React.ReactNode-
fieldNames自定义数据字段名映射CascaderFieldNames-
changeOnSelect选择中间层时是否立即提交booleanfalse
expandTrigger展开触发方式"click" | "hover"click
clearable是否显示清除按钮booleanfalse
loadData懒加载回调(selectedOptions, meta) => void | Promise<void>-
contentWidth弹层宽度number | string"auto"
maxPanelHeight弹层最大高度number | string336
side弹层方向PopoverContentProps["side"]bottom
align弹层对齐方式PopoverContentProps["align"]start
sideOffset弹层偏移number8
name表单字段名。提交时会写入路径数组的 JSON 字符串string-
required是否必填boolean-
disabled是否禁用booleanfalse
readOnly是否只读。允许查看,但禁止改值booleanfalse
className / class触发器样式类名string-
style触发器原生样式React.CSSProperties-
sx触发器 sx 样式SxProps-
contentClassName / contentClass弹层样式类名string-
contentStyle弹层原生样式React.CSSProperties-
contentSx弹层 sx 样式SxProps-
optionClassName / optionClass选项样式类名string-
optionStyle选项原生样式React.CSSProperties-
optionSx选项 sx 样式SxProps-

CascaderOption

属性说明类型
label显示文本React.ReactNode
value节点值string
children子节点CascaderOption[]
disabled是否禁用boolean
isLeaf是否叶子节点。false 时可作为懒加载节点boolean
loading节点加载态boolean

CascaderValueChangeMeta

属性说明类型
reason变更原因"select" | "clear"
path解析后的路径string[]
options当前路径对应的选项对象CascaderOption[]
option本次触发的节点CascaderOption | undefined
labels当前路径对应的展示文本React.ReactNode[]
event原始事件React.SyntheticEvent | undefined

CascaderRef

方法说明
focus()聚焦触发器
blur()取消聚焦
open()打开面板
close()关闭面板
clear()清空当前路径
getValue()获取当前路径数组

行为规则 / 优先级

  • displayRender 优先于默认的 separator 拼接规则。
  • changeOnSelect 优先于“仅叶子节点提交”的默认行为。
  • renderOption 只改变面板行的视觉表现,不改变选择逻辑。
  • fieldNames 会统一作用于 label / value / children / disabled / isLeaf / loading 的读取。
  • loadData 只负责异步补齐数据,真正的 children 仍建议由外部 options 状态驱动更新。
  • clearable 只在当前路径非空时显示。
  • disabled 会禁用整个控件;readOnly 允许查看和展开,但禁止改值与清空。

Notes

  • value 的推荐模型是“路径数组”,不要把它当成单个字符串使用。
  • 如果 label 不是纯字符串,建议同时配合 displayRender 控制触发器文案。
  • 懒加载节点建议显式设置 isLeaf={false},这样组件会把它识别为可展开分支。
  • 表单提交时,name 对应的隐藏字段会写入路径数组的 JSON 字符串,例如 ["zhejiang","hangzhou"]
  • 交互上,触发器支持 Enter / ArrowDown 打开,Escape 关闭;面板内用 Tab 正常切换焦点。
  • 如果你需要完全不同的渲染布局,优先用 renderOptiondisplayRender,不要直接改数据结构。