使用场景
与 TreeSelect 组件的区别:
- TreeSelect:核心价值在于目标节点,层级结构是为了方便用户快速筛选出目标选项,最终的节点才是用户想要的内容,常见于文件/文件夹选择、组织架构、权限分配等场景。
- Cascader:核心价值在于路径,用户选择的不是一个孤立的点,而是一条从根到叶的完整路径,常用于地理位置、商品分类等场景。
代码演示
如何引入
import { Cascader } from '@chenzy-design/svelte'; 基本用法
最简单的用法,默认只可以选叶子节点。
多选
设置 multiple,可以进行多选。
可搜索的
通过设置 filterTreeNode 属性可支持搜索功能。默认对 label 值进行搜索(使用字符串的 includes 方法进行匹配,不区分大小写),可通过 treeNodeFilterProp 指定其他属性值进行搜索。默认搜索结果只会展示叶子结点的路径,想要显示更多的结果,可以设置 filterLeafOnly 为 false。
filterLeafOnly=false:
Label 为 Snippet,指定其他属性进行搜索
可搜索的多选
支持多选和搜索同时使用,在这种场景下,可以通过按下 BackSpace 键来删除对应的已选项目。
可以使用 filterSorter 对筛选后的数据进行排序。
如果想要自定义渲染搜索后的选项,可以使用 filterRender 实现整行的自定义渲染,snippet 入参含 className(默认选项容器类名)、inputValue(搜索栏内容)、disabled、data(搜索结果数据)、selected(单选时的选中状态)、checkStatus(多选时的选中状态 {checked, halfChecked})、onClick(单选点击选中回调)、onCheck(多选点击选中回调)。
鼠标 hover 到选项可查看被省略文本完整内容
如果搜索结果中存在大量 Option,可以通过设置 virtualizeInSearch 开启搜索结果面板的虚拟化来优化性能。virtualizeInSearch 是一个包含 height、width、itemSize 的对象。
限制标签展示数量
在多选的场景中,利用 maxTagCount 可以限制展示的标签数量,超出部分将以 +N 的方式展示。使用 showRestTagsPopover 可以设置在超出 maxTagCount 后,hover +N 是否显示 Popover,默认为 false。并且,还可以在 restTagsPopoverProps 属性中配置 Popover。
限制选中数量
在多选的场景中,利用 max 可以限制多选选中的数量。超出 max 后将触发 onExceed 回调。
选择即改变
在单选的情况下,还可以通过设置 changeOnSelect,允许选中父级选项。
自定义显示
可以通过 displayProp 设置回填选项显示的属性值,默认为 label。
也可以通过 Snippet 型 prop 设定返回格式(Svelte 5 不支持函数返回 Snippet 这类 React render-prop 直译,故对齐 Semi 语义时拆成两个 Snippet 型 prop)。单选 (multiple=false) 时用 displayRenderSingle(入参为 labelPath 字符串数组)。多选 (multiple=true) 时用 displayRenderTag(每条 tag 各 render 一次,入参为 entity + idx),其中 entity 为节点的相关数据:
| 属性 | 说明 | 类型 |
|---|---|---|
| children | 子节点列表 | CascaderEntity[] |
| data | 节点原始数据 | CascaderNode |
| ind | 本节点在其父节点 children 数组中的下标 | number |
| key | 祖先累积 key | string |
| level | 节点层级(从 0 开始) | number |
| parent | 父节点 | CascaderEntity |
| parentKey | 父节点 key | string |
| path | 祖先累积 key 数组 | string[] |
| valuePath | 祖先原始 value 数组 | string[] |
单选
多选
单选
多选
自定义分隔符
可以通过 separator 设置分隔符,包括:搜索时显示在下拉框的内容以及单选时回显到 Trigger 的内容的分隔符。
禁用
严格禁用
可以使用 disableStrictly 来开启严格禁用。开启严格禁用后,当节点是 disabled 的时候,则不能通过子级或者父级的关系改变选中状态。以下面的 demo 为例,节点「宁波市」开启了严格禁用,因此,当我们改变其父节点「浙江省」的选中状态时,也不会影响到节点「宁波市」的选中状态。
展示子菜单的时机与点击选中
可以使用 showNext 设置展开 Dropdown 子菜单的触发时机,可选:click(默认)、hover。在多选模式下,你可以通过 clickToSelect 开启点击任意节点即选中的功能。这个 API 在配合 showNext="hover" 使用时特别有用:鼠标悬浮展开子菜单,点击则选中当前节点。
在顶部/底部渲染附加项
我们在级联选择器的顶部、底部分别预留了插槽,你可以通过 topSlot 或 bottomSlot 来设置。
受控
传入 value 时即为受控组件,可以配合 onChange 使用。
自动合并 value
在多选(multiple=true)场景中,当我们选中祖先节点时,如果希望 value 不包含它对应的子孙节点,则可以通过 autoMergeValue 来设置,默认为 true。当 autoMergeValue 和 leafOnly 同时开启时,后者优先级更高。
仅叶子节点
在多选时,可以通过开启 leafOnly 来设置 value 只包含叶子节点,即显示的 Tag 和 onChange 的参数 value 只包含叶子节点。
节点选中关系
多选时,可以使用 checkRelation 来设置节点之间选中关系的类型,可选:related(默认)、unRelated。当选中关系为 unRelated 时,意味着节点之间的选中互不影响。
动态更新数据
异步加载数据
可以使用 loadData 实现异步加载数据。不能与搜索同时使用。
远程搜索
设置 remote 后,搜索输入不再走本地匹配,而是仅触发 onSearch 回调,由你根据输入异步拉取 treeData。这与 Select 的 remote 行为一致。搜索时建议自行处理防抖、竞态保护、loading 提示、空输入还原等。
超长列表
当你的数据结构层级特别深时,Cascader 下拉菜单可能会超出屏幕,此时我们建议为下拉菜单设置 overflow-x: auto 以及一个合适的 width 宽度(建议以 N+0.5 列的宽度为准,最右侧显示半列,以给用户一种右侧尚有待展开项,可以水平方向滚动的视觉暗示)。
自定义 Trigger
如果默认的触发器样式满足不了你的需求,可以用 triggerRender 自定义选择框的展示。
triggerRender 入参如下
interface TriggerRenderProps {
/* 是否禁用 Cascader */
disabled: boolean;
/**
* 已选中的 node 在 treeData 中的层级位置,如下例子,
* 当选中浙江省-杭州市-萧山区时,此处 value 为 '0-0-1'
*/
value?: string | Set<string>;
/* 当前 Input 框的输入值 */
inputValue: string;
/**
* 用于更新 input 框值的函数,当你在 triggerRender 自定义的
* Input 组件值更新时,你应该调用该函数,用于向 Cascader 内部
* 同步状态,使用时需要设置 filterTreeNode 参数非 false
*/
onSearch: (inputValue: string) => void;
/* 用于清空值的函数(传入点击事件,用于 stopPropagation 阻止冒泡触发展开/关闭面板) */
onClear: (e?: MouseEvent) => void;
/* Placeholder */
placeholder?: string;
/* 用于删除单个 item,入参为层级位置 */
onRemove: (pos: string) => void;
} API 参考
Cascader
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| arrowIcon | 自定义右侧下拉箭头 Icon | Snippet | - |
| autoAdjustOverflow | 是否自动调整下拉框展开方向,用于边缘遮挡时自动调整展开方向 | boolean | true |
| autoMergeValue | 开启后,当某个父节点被选中时,value 将不包括该节点的子孙节点。不支持动态切换 | boolean | true |
| bottomSlot | 底部插槽 | Snippet | - |
| borderless | 无边框模式 | boolean | false |
| changeOnSelect | 是否允许选择非叶子节点 | boolean | false |
| checkRelation | 多选时,节点之间选中状态的关系,可选:related、unRelated | string | related |
| class | 选择框的 className 属性 | string | - |
| clearIcon | 可用于自定义清除按钮,showClear 为 true 时有效 | Snippet | - |
| defaultOpen | 设置是否默认打开下拉菜单 | boolean | false |
| defaultValue | 指定默认选中的条目 | string \| number \| array | - |
| disabled | 是否禁用 | boolean | false |
| disableStrictly | 开启严格禁用后,当节点是 disabled 时,不能通过子级或父级的关系改变选中状态 | boolean | false |
| displayProp | 设置回填选项显示的属性值 | string | label |
| displayRenderSingle | 单选自定义触发器回显内容,入参为 labelPath 字符串数组 | Snippet<[string[]]> | - |
| displayRenderTag | 多选每条 tag 的自定义回填内容,每条 tag 各 render 一次,入参为完整 Entity + idx | Snippet<[CascaderEntity, number]> | - |
| dropdownClassName | 下拉菜单的 className 属性 | string | - |
| dropdownStyle | 下拉菜单的样式 | string | - |
| emptyContent | 当搜索无结果时展示的内容 | string \| Snippet | 暂无数据 |
| filterLeafOnly | 搜索结果是否只展示叶子结点路径 | boolean | true |
| filterRender | 自定义渲染筛选后的选项;传入后接管点击选中,单选用回传的 onClick/selected,multiple 用 onCheck/checkStatus 自绘勾选交互 | Snippet<[{ path, data, inputValue, disabled, className, selected, onClick, onCheck, checkStatus }]> | - |
| filterSorter | 对筛选后的选项进行排序 | (a, b, input: string) => number | - |
| filterTreeNode | 设置筛选,true 用默认策略,传入函数自定义 | boolean \| ((inputValue, treeNodeString, data?) => boolean) | false |
| getPopupContainer | 指定父级 DOM,自定义需要设置 position: relative | () => HTMLElement | () => document.body |
| keyMaps | 自定义节点中 value、label、children、disabled、isLeaf 的字段 | object | - |
| leafOnly | 多选时设置 value 只包含叶子节点。不支持动态切换 | boolean | false |
| loadData | 异步加载数据,传入从根到该节点的完整选中路径,需要返回一个 Promise;不返回数据,加载结果需在 Promise 内自行更新 treeData | (selectOptions) => Promise<void> | - |
| max | 多选时限制选中数量,超出后触发 onExceed 回调 | number | - |
| maxTagCount | 多选时标签的最大展示数量,超出后以 +N 形式展示 | number | - |
| motion | 设置下拉框弹出的动画 | boolean | true |
| multiple | 设置多选 | boolean | false |
| placeholder | 选择框默认文字 | string | - |
| position | 方向,可选值同 Tooltip position | string | bottom |
| prefix | 前缀标签 | Snippet | - |
| remote | 是否开启远程搜索,行为与 Select 的 remote 一致 | boolean | false |
| restTagsPopoverProps | Popover 的配置属性 | object | {} |
| separator | 自定义分隔符 | string | / |
| showClear | 是否展示清除按钮 | boolean | false |
| showNext | 设置展开 Dropdown 子菜单的方式,可选:click、hover | string | click |
| showRestTagsPopover | 当超过 maxTagCount,hover +N 时,是否通过 Popover 显示剩余内容 | boolean | false |
| size | 选择框大小,可选 large、small、default | string | default |
| clickToSelect | 多选时,点击任意节点即可触发选中,常配合 showNext=“hover” 使用 | boolean | false |
| style | 选择框的样式 | string | - |
| suffix | 后缀标签 | Snippet | - |
| topSlot | 顶部插槽 | Snippet | - |
| treeData | 展示数据,具体属性参考 CascaderData | CascaderData[] | [] |
| treeNodeFilterProp | 搜索时输入项过滤对应的 CascaderData 属性 | string | label |
| triggerRender | 自定义触发器渲染方法 | Snippet | - |
| validateStatus | trigger 的校验状态,仅影响展示样式。可选:default、error、warning | string | default |
| value | (受控)选中的条目 | string \| number \| array | - |
| virtualizeInSearch | 搜索列表虚拟化,由 height、width、itemSize 组成 | object | - |
| zIndex | 下拉菜单的 zIndex | number | 1030 |
| onBlur | 失焦 Cascader 的回调 | (e) => void | - |
| onChange | 选中树节点时调用,默认返回选中项 path 的 value 数组 | (value) => void | - |
| onChangeWithObject | 设为 true 时,onChange 的入参类型会从 value 变为节点对象 | boolean | false |
| onClear | showClear 为 true 时,点击清空按钮触发的回调 | (e) => void | - |
| onDropdownVisibleChange | 下拉框切换时的回调 | (visible: boolean) => void | - |
| onExceed | 多选时,超出 max 后触发的回调 | (items) => void | - |
| onFocus | 聚焦 Cascader 的回调 | (e) => void | - |
| onLoad | 节点加载完毕时触发的回调 | (keys, data) => void | - |
| onSearch | 文本框值变化时回调 | (value: string) => void | - |
| onSelect | 被选中时调用,返回选中项的 value | (value) => void | - |
CascaderData
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| children | 子节点 | CascaderData[] | - |
| disabled | 不可选状态 | boolean | - |
| isLeaf | 叶子节点 | boolean | - |
| label | 展示的文本(必填) | string \| Snippet | - |
| loading | 正在加载 | boolean | - |
| value | 属性值(必填) | string \| number | - |
Methods
绑定在组件实例上的方法,可以通过 bind:this 拿到实例后调用:
| 方法 | 说明 |
|---|---|
| close | 调用时可以手动关闭下拉列表 |
| open | 调用时可以手动展开下拉列表 |
| focus | 调用时可以手动聚焦 |
| blur | 调用时可以手动失焦 |
| search | 手动触发搜索,需同时设置 filterTreeNode 开启搜索 |
Accessibility
ARIA
- Cascader 支持传入
aria-label、aria-describedby、aria-errormessage、aria-invalid、aria-labelledby、aria-required来表示该 Cascader 的相关信息。 - Cascader 支持通过按下 Enter 键来选中选项、清空选项、展开下拉框。
设计变量
变量 | 默认值 | 用法 |
|---|---|---|
| --cd-animation-duration-cascader-dropdown-in | 100ms | 级联选择下拉浮层弹出动画持续时间(组件消费) |
| --cd-animation-duration-cascader-dropdown-out | 100ms | 级联选择下拉浮层收起动画持续时间(组件消费) |
| --cd-animation-function-cascader-dropdown-in | cubic-bezier(0.215, 0.61, 0.355, 1) | 级联选择下拉浮层弹出动画插值函数(组件消费) |
| --cd-animation-function-cascader-dropdown-out | cubic-bezier(0.215, 0.61, 0.355, 1) | 级联选择下拉浮层收起动画插值函数(组件消费) |
| --cd-cascader-dropdown-motion-zoom-opacity-from | 0 | 浮层进场初始透明度(组件消费) |
| --cd-cascader-dropdown-motion-zoom-opacity-to | 1 | 浮层进场最终透明度(组件消费) |
| --cd-cascader-dropdown-motion-zoom-scale-from | 0.8 | 浮层进场初始缩放(组件消费) |
- 1