- 前端
- UI组件
- 设计系统
【免费下载链接】ant-design-vue
🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜
级联选择框(Cascader)是 ant-design-vue 中用于处理"多级关联数据"选择的核心组件,常用于省市区、组织层级、商品分类等具有父子层级关系的场景。本文将基于 components/cascader/index.en-US.md 官方文档,结合 components/cascader/index.tsx 源码实现与 components/cascader/demo 目录下的 14 个真实示例,系统讲解 Cascader 的全部配置项、事件、方法与高级用法,帮助你快速掌握该组件的完整能力。
When To Use:什么场景适合使用级联选择
官方文档给出了三个典型的适用场景:
- 需要从一组相互关联的数据集中进行选择,例如省/市/区、公司层级、事物分类等树状结构数据;
- 数据量大且具有多级分类,通过逐级分类拆分,降低单次选择的复杂度;
- 希望在一个浮层中完成级联选择,提供更好的用户体验。
简单来说,只要你的选择数据天然存在父子层级关系(如 components/cascader/demo/basic.vue 中的"省份 → 城市 → 景区"数据),级联选择框就是比普通下拉框更合适的交互方案。
基础用法:最简可运行的 Cascader
官方文档开篇给出了最基础的使用示例:
<a-cascader :options="options" v-model:value="value" />对应 components/cascader/demo/basic.vue 中的完整实现:
<template> <a-cascader v-model:value="value" :options="options" placeholder="Please select" /> </template> <script lang="ts" setup> import { ref } from 'vue'; import type { CascaderProps } from 'ant-design-vue'; const options: CascaderProps['options'] = [ { value: 'zhejiang', label: 'Zhejiang', children: [ { value: 'hangzhou', label: 'Hangzhou', children: [{ value: 'xihu', label: 'West Lake' }], }, ], }, { value: 'jiangsu', label: 'Jiangsu', children: [ { value: 'nanjing', label: 'Nanjing', children: [{ value: 'zhonghuamen', label: 'Zhong Hua Men' }], }, ], }, ]; const value = ref<string[]>([]); </script>需要注意两个关键点:
options是树形嵌套结构,每个节点可包含value、label与children;value是路径数组(如['zhejiang', 'hangzhou', 'xihu']),v-model:value双向绑定选中路径,而非单个叶子值。
组件底层基于vc-cascader实现(见 components/vc-cascader 目录),外层 components/cascader/index.tsx 负责与 ant-design-vue 的主题、表单、尺寸体系对接,并将内部 Select 的视觉样式复用到 Cascader 上。
API 总览:完整参数表
以下参数表完整继承自官方文档,并补充了参数的作用说明。默认引入方式为全局注册后的<a-cascader>标签。
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| allowClear | 是否允许清除 | boolean | true | |
| autofocus | 组件挂载时是否自动获取焦点 | boolean | false | |
| bordered | 是否有边框样式 | boolean | true | 3.2 |
| clearIcon | 自定义清除图标 | slot | - | 3.2 |
| changeOnSelect | (单选时生效)设为 true 后,每次选中都触发 change,允许只选父级 | boolean | false | |
| disabled | 是否禁用选择 | boolean | false | |
| displayRender | 展示已选项的渲染函数,可使用#displayRender="{labels, selectedOptions}" | ({labels, selectedOptions}) => VNode | labels => labels.join(' / ') | |
| popupClassName | 弹出浮层额外的 className | string | - | 4.0 |
| dropdownStyle | 弹出浮层额外的样式 | CSSProperties | {} | 3.0 |
| expandIcon | 自定义当前项展开图标 | slot | - | 3.0 |
| expandTrigger | 展开当前项的方式:点击或悬停 | click|hover | 'click' | |
| fieldNames | 自定义 label、value、children 的字段名 | object | { label: 'label', value: 'value', children: 'children' } | |
| getPopupContainer | 选择器浮层渲染到的父节点,默认渲染到body。出现定位问题时,可改为可滚动内容并设置相对定位 | Function(triggerNode) | () => document.body | |
| loadData | 动态加载选项,注意不能与showSearch同时使用 | (selectedOptions) => void | - | |
| maxTagCount | 最多显示的 tag 数量,responsive模式会消耗渲染性能 | number |responsive | - | 3.0 |
| maxTagPlaceholder | 未展示 tag 的占位内容 | v-slot | function(omittedValues) | - | 3.0 |
| multiple | 是否支持多选 | boolean | - | 3.0 |
| notFoundContent | 无匹配结果时展示的内容 | string | slot | 'Not Found' | |
| open | 控制级联浮层的显隐 | boolean | - | 3.0 |
| options | 级联数据源 | Option[] | - | |
| placeholder | 输入框占位符 | string | 'Please select' | |
| placement | 使用内置浮层对齐配置 | bottomLeft|bottomRight|topLeft|topRight | bottomLeft | 3.0 |
| removeIcon | 自定义移除图标 | slot | - | 3.2 |
| searchValue | 设置搜索值,需配合showSearch使用 | string | - | 3.0 |
| showSearch | 单选模式下是否显示搜索框 | boolean | object | false | |
| size | 输入框尺寸 | large|default|small | default | |
| status | 校验状态 | 'error' | 'warning' | - | 3.3.0 |
| suffixIcon | 自定义后缀图标 | string | VNode | slot | - | |
| showCheckedStrategy | 多选时选中项的展示方式:Cascader.SHOW_CHILD只显示子节点;Cascader.SHOW_PARENT仅当父节点下所有子节点都被选中时才显示父节点 | Cascader.SHOW_PARENT|Cascader.SHOW_CHILD | Cascader.SHOW_PARENT | 3.3.0 |
| tagRender | multiple模式下自定义 tag 渲染 | slot | - | 3.0 |
| value(v-model) | 选中的值 | string[] | number[] | - |
与 Select 体系的继承关系
从源码看,components/cascader/index.tsx 中的cascaderProps()通过...omit(vcCascaderProps(), ['customSlots', 'checkable', 'options'])继承了vc-cascader的全部属性,仅排除掉内部使用的customSlots、checkable与options,再补充声明multiple、size、bordered、placement、suffixIcon、status、popupClassName以及已废弃的dropdownClassName等属性。同时组件在setup中调用useConfigInject('cascader', props)注入 ConfigProvider 配置,并使用useSelectStyle与useStyle分别应用 Select 与 Cascader 的样式(components/cascader/style/index.ts),因此它在外观、尺寸、状态上与 Select 保持完全一致的设计语言。
注意:
dropdownClassName已被标记为@deprecated,源码会在非生产环境通过devWarning提示改用popupClassName(见 components/cascader/index.tsx)。
数据源 Option:结构、字段与叶子节点
官方文档定义的Option接口如下:
interface Option { value: string | number; label?: VNode; disabled?: boolean; children?: Option[]; // 指定该节点是否为叶子节点(当设置了 `loadData` 时生效)。 // `false` 会强制将该树节点视为父节点。 // 即使当前节点没有 children,也会显示展开图标。 isLeaf?: boolean; }各字段含义:
- value:必填,节点值,最终会以路径数组形式出现在
v-model:value中; - label:节点展示文案,也支持 VNode 以便渲染复杂内容;
- disabled:禁用该节点(参考 components/cascader/demo/disabled-option.vue);
- children:子节点数组,形成级联层级;
- isLeaf:与
loadData配合使用。当某节点isLeaf: false且无 children 时,会展示展开图标并触发加载回调;默认情况下无 children 的节点会被视为叶子节点。
自定义字段名 fieldNames
当后端返回的数据字段不叫label/value/children时,可通过fieldNames重映射,如 components/cascader/demo/fields-name.vue 所示:
<a-cascader v-model:value="value" :field-names="{ label: 'name', value: 'code', children: 'items' }" :options="options" placeholder="Please select" />此时数据需写成:
const options = [ { code: 'zhejiang', name: 'Zhejiang', items: [ { code: 'hangzhou', name: 'Hangzhou', items: [{ code: 'xihu', name: 'West Lake' }] }, ], }, ];changeOnSelect:允许只选父级
默认情况下,Cascader 要求必须选中叶子节点才触发 change。当希望"选择到某一级就立即提交"(例如只选到省份)时,开启changeOnSelect即可,见 components/cascader/demo/change-on-select.vue:
<a-cascader v-model:value="value" :options="options" placeholder="Please select" change-on-select />官方文档特别注明:该属性仅对单选模式生效。
expandTrigger 与 expandIcon:展开交互与图标定制
移入展开
通过expand-trigger="hover"可改为鼠标移入即展开下级菜单、点击完成选择,见 components/cascader/demo/hover.vue:
<a-cascader v-model:value="value" :options="options" expand-trigger="hover" placeholder="Please select" />默认值为'click',即点击展开。
自定义展开图标
expandIcon是一个 slot,可完全替换默认的展开箭头。从源码看,未提供该 slot 时组件会根据direction(RTL 与否)自动选择RightOutlined或LeftOutlined作为展开图标(components/cascader/index.tsx),并在节点处于加载态时渲染带spin的LoadingOutlined加载图标。
搜索 showSearch:在级联中直接搜选项
单选模式下通过showSearch开启搜索。官方文档的用法示例为:
<a-cascader v-model:value="value" :options="options" :show-search="{ filter }" placeholder="Please select" />对应的自定义filter函数(见 components/cascader/demo/search.vue):
import type { ShowSearchType } from 'ant-design-vue/es/cascader'; const filter: ShowSearchType['filter'] = (inputValue, path) => { return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1); };filter接收(inputValue, path)两个参数,path是从根到当前节点的完整路径数组,返回true表示该选项进入过滤结果集。上面的实现表示"路径上任一节点的 label 包含输入值即命中"。
showSearch 对象配置项
当showSearch传对象时,支持以下字段:
| Property | Description | Type | Default |
|---|---|---|---|
| filter | 过滤函数,接收 inputValue 和 path,返回 true 则包含该选项,否则排除 | function(inputValue, path): boolean | |
| limit | 过滤结果的数量上限 | number | false | 50 |
| matchInputWidth | 结果列表宽度是否等于输入框宽度 | boolean | |
| render | 渲染过滤结果,可使用#showSearchRender="{inputValue, path}" | function({inputValue, path}): VNode | |
| sort | 对过滤结果排序 | function(a, b, inputValue) |
从源码看(components/cascader/index.tsx),当showSearch为真值时,组件会将其与内置的defaultSearchRender合并:默认渲染逻辑会对命中的关键词做高亮(用-menu-item-keyword样式包裹匹配片段,见 components/cascader/index.tsx),并将路径各级 label 用/连接展示。
注意:
showSearch暂不支持服务端搜索(官方 demo 中引用了 ant-design/ant-design 的 issue #5547 说明此限制),搜索在客户端完成;同时官方文档强调loadData与showSearch无法一起使用。
多选 multiple:批量选择与展示策略
multiple模式自 3.0 起支持,见 components/cascader/demo/multiple.vue:
<h4>Cascader.SHOW_PARENT</h4> <a-cascader v-model:value="value" style="width: 100%" multiple max-tag-count="responsive" :options="options" placeholder="Please select" /> <h4>Cascader.SHOW_CHILD</h4> <a-cascader v-model:value="value" style="width: 100%" multiple max-tag-count="responsive" :options="options" placeholder="Please select" :show-checked-strategy="Cascader.SHOW_CHILD" />多选模式下需要理解两个核心概念:
showCheckedStrategy:控制已选项的展示方式。默认Cascader.SHOW_PARENT——当父节点下所有子节点都被选中时,只展示父节点;Cascader.SHOW_CHILD则始终展示叶子节点。这两个常量通过Cascader.SHOW_PARENT/Cascader.SHOW_CHILD静态属性访问,在源码中由Object.assign(Cascader, { SHOW_CHILD, SHOW_PARENT })挂载(components/cascader/index.tsx),底层实现在 components/vc-cascader 中。maxTagCount:限制 tag 展示数量,responsive会根据宽度自适应折叠。
与多选相关的补充说明:
displayRender在multiple模式下不生效,源码会在非生产环境抛出警告,提示改用tagRender(components/cascader/index.tsx);tagRenderslot 可自定义每个已选项 tag 的内容与样式,如 components/cascader/demo/tagRender.vue 中将其渲染为蓝色<a-tag>:
<a-cascader v-model:value="value" multiple :options="options" placeholder="Please select"> <template #tagRender="data"> <a-tag :key="data.value" color="blue">{{ data.label }}</a-tag> </template> </a-cascader>loadData:大数据量下的动态加载
当级联数据量很大、子节点需要按需请求时,使用loadData懒加载子选项。参考 components/cascader/demo/lazy.vue:
<a-cascader v-model:value="value" :options="options" :load-data="loadData" placeholder="Please select" change-on-select />const options = ref<CascaderProps['options']>([ { value: 'zhejiang', label: 'Zhejiang', isLeaf: false }, { value: 'jiangsu', label: 'Jiangsu', isLeaf: false }, ]); const loadData: CascaderProps['loadData'] = selectedOptions => { const targetOption = selectedOptions[selectedOptions.length - 1]; targetOption.loading = true; // 模拟异步请求子选项 setTimeout(() => { targetOption.loading = false; targetOption.children = [ { label: `${targetOption.label} Dynamic 1`, value: 'dynamic1' }, { label: `${targetOption.label} Dynamic 2`, value: 'dynamic2' }, ]; options.value = [...options.value]; }, 1000); };使用要点:
- 顶层选项需要设置
isLeaf: false,否则组件会把无 children 的节点当作叶子节点,不触发加载; - 加载过程中给节点设置
loading = true,组件会展示旋转加载图标; - 加载完成后将
children写入目标节点,并用展开运算符创建新数组触发响应式更新; - 官方文档明确:
loadData不能与showSearch同时使用。
自定义渲染:displayRender 与自定义触发器
自定义已选项展示
displayRender接收{ labels, selectedOptions },可用于在输入框内定制已选项的展示,例如 components/cascader/demo/custom-render.vue 为最后一项附加可点击的邮编链接:
<a-cascader v-model:value="value" placeholder="Please select" :options="options" style="width: 100%"> <template #displayRender="{ labels, selectedOptions }"> <span v-for="(label, index) in labels" :key="selectedOptions[index].value"> <span v-if="index === labels.length - 1"> {{ label }} ( <a @click="e => handleAreaClick(e, label, selectedOptions[index])"> {{ selectedOptions[index].code }} </a> ) </span> <span v-else>{{ label }} /</span> </span> </template> </a-cascader>默认展示为各级 label 用/连接(默认值labels => labels.join(' / '))。源码将displayRender同时兼容函数与 slot 两种传法:displayRender={props.displayRender || slots.displayRender}(components/cascader/index.tsx)。
自定义触发器
Cascader 选择框默认是一个带前缀图标的下拉触发区域,可通过 slot 完全替换触发 UI,实现"自定义触发器"(参考 components/cascader/demo/custom-trigger.vue),适合把级联面板嵌入按钮、文本等任意交互元素中。
事件、v-model 与实例方法
事件
| Events Name | Description | Arguments | version | |
|---|---|---|---|---|
| change | 完成级联选择时触发 | (value, selectedOptions) => void | - | |
| dropdownVisibleChange | 浮层显示/隐藏时触发 | (value) => void | - | 3.0 |
| search | 输入值变化时触发 | (value) => void | - | 1.5.4 |
其中change事件在源码中通过handleChange转发:依次触发update:value(驱动v-model:value)、change,并调用表单上下文的onFieldChange通知 FormItem 校验(components/cascader/index.tsx),因此组件在 Form 中能自动参与校验与字段状态同步。
实例方法
| Name | Description |
|---|---|
| blur() | 移除焦点 |
| focus() | 获取焦点 |
组件通过expose({ focus, blur })暴露这两个方法(components/cascader/index.tsx),可配合模板 ref 调用,例如<a-cascader ref="cascaderRef" />后执行cascaderRef.value?.focus()。测试文件 components/cascader/tests/index.test.js 中通过共享的focusTest工具验证了焦点行为的正确性。
外观与状态:尺寸、边框、校验与浮层
- size:
large/default/small三档尺寸,源码会为large、small分别添加-lg、-sm修饰类(components/cascader/index.tsx),并优先读取 ConfigProvider 与 Space Compact 注入的尺寸; - bordered:3.2 起支持,设为
false得到无边框样式,对应类名-borderless; - status:3.3.0 起支持
error/warning校验状态,源码通过getMergedStatus合并 FormItem 上下文状态与自身状态,并应用getStatusClassNames生成状态类名(components/cascader/index.tsx),在 Form 中可自动继承校验状态; - placement:
bottomLeft/bottomRight/topLeft/topRight,默认bottomLeft;在 RTL 环境下默认自动切换为bottomRight(components/cascader/index.tsx); - popupClassName / dropdownStyle:分别设置浮层的额外类名与内联样式,用于浮层定制;
- getPopupContainer:浮层默认渲染到
document.body,当父容器发生滚动或定位(如overflow: hidden)导致浮层位置异常时,可传入函数将其渲染到可滚动容器内; - allowClear / clearIcon / removeIcon / suffixIcon:清除能力与图标定制,图标相关处理复用 Select 的
getIcons工具(components/cascader/index.tsx),且clearIcon、removeIcon均支持 slot 形式(3.2 起); - notFoundContent:无匹配结果时显示的内容,默认
'Not Found',源码中未提供时会回退到 ConfigProvider 的renderEmpty('Cascader')空状态(components/cascader/index.tsx)。
源码架构小结
从整体架构看,Cascader 采用"外层组件 + vc-cascader 内核"的分层设计:
- components/vc-cascader 是组件内核,包含
Cascader.tsx主文件、OptionList面板渲染、useSearchConfig/useSearchOptions搜索逻辑、useEntities节点实体管理、useDisplayValues已选项展示值计算等 hooks,以及commonUtil/treeUtil树工具; - components/cascader/index.tsx 是面向用户的外层封装,负责:合并 vc 属性并补充 Vue 化声明、注入 ConfigProvider / Form / DisabledContext 上下文、计算前缀类名与 SSR 样式、组装展开/清除/后缀/加载图标、转发事件并暴露 focus/blur 方法;
- components/cascader/demo 提供 14 个覆盖基本用法、搜索、多选、懒加载、字段映射、hover、自定义渲染、tag 定制等场景的完整示例;
- components/cascader/tests/index.test.js 覆盖面板显隐、搜索过滤、焦点行为等核心逻辑,是验证组件行为可靠性的直接依据。
总结
ant-design-vue 的 Cascader 组件以"路径数组"作为数据模型,通过丰富的配置项覆盖了从最基础的省市区选择到多选、搜索、懒加载、自定义渲染等全部实际场景。掌握options树结构、fieldNames字段映射、changeOnSelect父级选择、showCheckedStrategy多选展示策略、loadData动态加载与showSearch搜索配置这六个核心能力,即可在项目中游刃有余地处理一切层级关联数据的选择需求。
- 前端
- UI组件
- 设计系统
【免费下载链接】ant-design-vue
🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜
相关推荐
Hugo Theme Zzo画廊功能详解:创建令人惊艳的图片展示页面
Hugo Theme Zzo画廊功能详解:创建令人惊艳的图片展示页面 想要为你的Hugo博客添加专业的图片展示功能吗?🎨 Hugo Theme Zzo提供了强
前端UI组件设计系统ant-design Cascader 级联选择组件完全指南:API、数据源结构与实战用法
ant design Cascader 级联选择组件完全指南:API、数据源结构与实战用法 级联选择框(Cascader)是 ant design 中处理省市区
UI组件前端设计系统别再被环境配置劝退:零基础也能跑起第一个 AI 模型的两种路径
别再被环境配置劝退:零基础也能跑起第一个 AI 模型的两种路径 实习生小林入职第一天,leader 丢给他一个任务:跑通一个情感分析模型。他兴冲冲复制了一段代码
前端UI组件设计系统
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考