资讯动态

Cascader 级联选择器完全指南:Element Plus 层级数据选择的配置、源码原理与最佳实践

发布时间:2026/9/11 13:05:02 来源:尧图企业网站定制
Cascader 级联选择器完全指南Element Plus 层级数据选择的配置、源码原理与最佳实践【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plusElement Plus 是 Vue 3 生态中主流的 UI 组件库本仓库为 element-plus 官方仓库。当业务数据具有清晰的层级结构——例如省市区、组织架构、商品分类——时Cascader级联选择器是查看与选择这类数据的标准答案。本文以仓库中 级联选择器官方文档 为核心骨架结合 cascader 组件源码、cascader-panel 面板源码 与 Node 树节点实现完整讲解el-cascader的全部配置项、事件、插槽、暴露方法以及CascaderPanel、CascaderProps的底层原理。读完本文你将掌握从基础绑定、禁用、清空、多选、动态加载、搜索过滤到虚拟滚动、自定义插槽的完整实战方案。一、基础用法从 options 数组到两种展开方式Cascader 的核心数据来源是options属性它是一个嵌套数组。每个节点对象默认使用value、label、children三个字段来描述值、展示文本与子节点。组件内部会把这份纯数据转换成Node节点树参见 Node 构造函数const { value: valueKey, label: labelKey, children: childrenKey } config const childrenData data[childrenKey] as ChildrenData ... this.value data[valueKey] as CascaderNodeValue this.label data[labelKey] as string this.children (childrenData || []).map((child) new Node(child, config, this))子选项的展开方式由props.expandTrigger控制可选click默认与hover。仓库示例 basic.vue 同时演示了两种模式template div classm-4 pChild options expand when clicked (default)/p el-cascader v-modelvalue :optionsoptions changehandleChange / /div div classm-4 pChild options expand when hovered/p el-cascader v-modelvalue :optionsoptions :propsprops changehandleChange / /div /template script langts setup import { ref } from vue const value ref([]) const props { expandTrigger: hover as const, } const handleChange (value) { console.log(value) } const options [ { value: guide, label: Guide, children: [ { value: disciplines, label: Disciplines, children: [ { value: consistency, label: Consistency }, { value: feedback, label: Feedback }, { value: efficiency, label: Efficiency }, { value: controllability, label: Controllability }, ], }, { value: navigation, label: Navigation }, ], }, // ...更多层级 ] /script几点关键细节v-model绑定的值在默认情况下emitPath为true是从根节点到当前节点的整条路径值数组例如[guide, disciplines, consistency]而不是叶子节点的单个值。change事件在绑定值变化时触发回调参数即当前值。expandTrigger: hover配合props.hoverThreshold默认 500 毫秒使用鼠标悬停超过阈值才会展开子菜单避免误触。该默认值定义在 DefaultProps。二、禁用选项disabled 字段与字段名定制在 option 对象中为某个节点设置disabled: true该节点即被禁用。仓库示例 option-disabling.vue 中Guide一级节点设置了disabled: true其整棵子树都不可选择。默认情况下 Cascader 读取每个 option 对象中的disabled字段。如果你使用的数据结构用了其他字段名可以通过props.disabled指定同理value、label、children字段名也都可以定制。这一定制能力来自 config.ts 中定义的DefaultPropsvalue: value, label: label, children: children, leaf: leaf, disabled: disabled,而底层的禁用判定逻辑位于 Node.isDisabled它不仅检查当前节点自身还会在非checkStrictly模式下向上追溯父节点——只要父节点被禁用子孙节点全部视为禁用get isDisabled(): boolean { const { data, parent, config } this const { disabled, checkStrictly } config const isDisabled isFunction(disabled) ? disabled(data, this) : !!data[disabled] return isDisabled || (!checkStrictly !!parent?.isDisabled) }三、清空与自定义清空图标设置clearable属性后当有选中值且鼠标悬停在输入框上时会出现清空图标点击即可清空选中值。自 2.11.0 版本起可通过clear-icon属性自定义清空图标组件。源码中该属性的默认值是内置的CircleClose图标clearIcon: { type: iconPropType, default: CircleClose, },用法示例见 clear-icon.vueel-cascader v-modelvalue :optionsoptions clearable :clear-iconSomeIcon /自 2.7.7 起点击清空图标会触发clear事件可用来做额外的埋点或状态重置。四、仅显示最后一级show-all-levels默认情况下show-all-levels true输入框中显示选中项的完整路径各层级之间用separator分隔默认 / 可通过separator属性自定义。设置show-all-levels false后输入框只显示最后一级的文字。路径文字的计算逻辑在 Node.calcTextcalcText(allLevels: boolean, separator: string) { const text allLevels ? this.pathLabels.join(separator) : this.label this.text text return text }el-cascader v-modelvalue :optionsoptions :show-all-levelsfalse /五、多选multiple 与标签折叠多选模式需要把multiple: true写进props对象。官方文档特别强调了一个易踩的坑正确写法必须通过变量绑定template el-cascader :propsprops / /template script langts setup const props { multiple: true } /script错误写法对象字面量直接绑定对 cascader 无效template !-- Object literal binding here is invalid syntax for cascader -- el-cascader :props{ multiple: true } / /template多选模式下所有选中项默认以标签Tag形式全部展示配合以下属性可控制折叠行为示例见 multiple-selection.vuecollapse-tags是否折叠超出部分的标签。true时仅显示max-collapse-tags个标签默认 1其余合并为N的折叠文本。max-collapse-tags2.3.10最多显示的标签数量默认1使用前提是collapse-tags true。collapse-tags-tooltip鼠标悬停折叠文本时是否以 Tooltip 展示全部选中标签使用前提同样是collapse-tags true。max-collapse-tags-tooltip-height2.10.2折叠标签 Tooltip 的最大高度。el-cascader :optionsoptions :props{ multiple: true } collapse-tags collapse-tags-tooltip :max-collapse-tags3 clearable /从源码看maxCollapseTags默认值1、collapseTagsTooltip默认false均在 cascader.ts 中定义。六、选择任意层级checkStrictly在单选中默认只能选叶子节点多选中勾选父节点会联动勾选其全部叶子节点父节点本身不会被记录为选中值。当需要父、子节点互不关联、任意层级都可选择时设置props.checkStrictly true即可示例见 any-level.vue。checkStrictly影响两处底层行为禁用判定Node.isDisabled中的(!checkStrictly !!parent?.isDisabled)——开启后父节点禁用不再连坐子节点。勾选联动见 Node.doCheckdoCheck(checked: boolean) { if (this.checked checked) return const { checkStrictly, multiple } this.config if (checkStrictly || !multiple) { this.checked checked } else { // bottom up to unify the calculation of the indeterminate state this.broadcast(checked) this.setCheckState(checked) this.emit() } }可以看到checkStrictly true时节点勾选状态彼此独立否则通过broadcast自顶向下广播与emit自底向上回溯完成父子联动并借助setCheckState计算半选indeterminate状态。七、动态加载lazy 与 lazyLoad当数据量极大或子级数据依赖服务端按需获取时可开启动态加载。设置props.lazy true并实现props.lazyLoad(node, resolve, reject)node当前被点击展开的节点对象resolve加载完成后的回调必须调用参数为子节点数据数组reject2.11.5 起支持的拒绝回调用于标记加载失败。更准确地展示节点状态可以给数据加leaf字段可通过props.leaf自定义字段名来声明是否为叶子节点不声明时组件会依据是否还有子节点数据来推断。推断逻辑见 Node.isLeafget isLeaf(): boolean { const { data, config, childrenData, loaded } this const { lazy, leaf } config const isLeaf isFunction(leaf) ? leaf(data, this) : data[leaf] return isUndefined(isLeaf) ? lazy !loaded ? false : !(isArray(childrenData) childrenData.length) : !!isLeaf }仓库示例 dynamic-loading.vue 演示了完整的模拟异步加载流程script langts setup import type { CascaderProps } from element-plus let id 0 const props: CascaderProps { lazy: true, lazyLoad(node, resolve) { const { level } node setTimeout(() { const nodes Array.from({ length: level 1 }).map((item) ({ value: id, label: Option - ${id}, leaf: level 2, })) // Invoke resolve callback to return the child nodes data and indicate the loading is finished. resolve(nodes) }, 1000) }, } /script这里leaf: level 2表示深度达到 2 级后不再继续加载形成有限深度树。加载状态由Node.loading字段驱动默认false加载完成后的子节点通过appendChild挂入节点树。八、搜索过滤filterable、filter-method 与 before-filter设置filterable后输入关键词即可检索选项示例见 filterable.vue。默认匹配规则是节点的 label在show-all-levels true时含父级路径拼接后的文本即Node.text包含关键词即命中。默认实现就写在 cascader.tsfilterMethod: { type: definePropType(node: CascaderNode, keyword: string) boolean(Function), default: (node: CascaderNode, keyword: string) node.text.includes(keyword), },自定义搜索逻辑时传入filter-method函数签名(node: CascaderNode, keyword: string) boolean返回true表示命中。两个配套属性debounce输入关键词后的防抖延迟毫秒默认300。搜索高频、数据量大时建议调大避免每次按键都执行全树扫描。before-filter过滤前的钩子函数参数为将要过滤的关键词。返回false或返回一个被 reject 的 Promise 时本次过滤会被中止。适合做未登录禁止搜索空关键词直接放行等前置拦截。九、自定义节点内容与搜索建议项9.1 节点自定义内容default 插槽通过默认插槽可自定义下拉面板中每个节点的展示内容作用域中可拿到当前节点的Node对象node和原始数据data。示例 custom-content.vue 在叶子节点旁附加了子节点数量el-cascader :optionsoptions template #default{ node, data } span{{ data.label }}/span span v-if!node.isLeaf ({{ data.children.length }}) /span /template /el-cascadernode.isLeaf即上文所述的叶子判定逻辑可在模板中直接使用。9.2 自定义搜索建议项suggestion-item 插槽2.9.5过滤模式下默认的建议项渲染为匹配路径文本。使用suggestion-item插槽可完全自定义建议项内容作用域中拿到item即CascaderNode。适合在建议项中高亮关键词、附加图标等场景示例见 custom-suggestion-item.vue。十、CascaderPanel脱离输入框的独立级联面板CascaderPanel是Cascader的核心面板组件el-cascader的展示与交互几乎都委托给它。它支持单选、多选、动态加载、任意层级选择等全部特性但没有输入框、清空按钮等外壳能力适合嵌入自定义弹层或抽屉中示例见 panel.vueel-cascader-panel :optionsoptions :propsprops /面板同样接收options与props还额外支持virtual-scroll、item-size、height2.14.0三个虚拟滚动属性。面板向外暴露getCheckedNodes(leafOnly?)与clearCheckedNodes()两个方法。从组件树关系看Cascader组合了CascaderPanel与 Input/popper 等外壳组件二者共用 CascaderCommonPropsmodelValue、options、props、virtualScroll、itemSize、height。十一、更多进阶能力2.10 系列11.1 自定义标签tag 插槽2.10.3多选模式下的选中标签可通过tag插槽自定义作用域提供{ data, deleteTag }deleteTag用于手动移除某个标签。注意使用自定义标签后collapse-tags、collapse-tags-tooltip、max-collapse-tags将不再生效折叠能力需自行在插槽内实现。11.2 选中展示策略show-checked-strategy2.10.5多选模式下控制已选值的展示/回填粒度child默认展示所有被选中的叶子节点parent当某个父节点的子节点全部被选中时只展示该父节点更整洁适合整组选择语义。从源码看该属性只接受parent | child两个枚举值默认child定义于 cascader.ts。注意它只影响值的展示与回显策略checkStrictly仍决定勾选时的联动行为。11.3 点击节点勾选checkOnClickNode / checkOnClickLeaf / showPrefix2.10.5默认多选模式下只能点击每行左侧的前缀图标radio/checkbox完成勾选。以下属性用于调整交互checkOnClickNode是否允许点击节点文本本身进行勾选/取消勾选需与multiple或checkStrictly搭配使用checkOnClickLeaf是否只对叶子节点启用点击勾选默认true即默认点击叶子也可勾选showPrefix是否显示前缀图标默认true。如果通过checkOnClickNode让整个节点可点可设置false隐藏图标。对应默认值见 DefaultProps。11.4 自定义下拉头部与底部header / footer 插槽2.10.5通过header与footer插槽可在下拉面板顶部/底部插入自定义内容如全选/清空按钮、统计文案示例见 custom-header-footer.vue。十二、大数据量性能优化虚拟滚动2.14.0处理海量选项时设置virtual-scroll为true可开启虚拟滚动只渲染可视区域内的节点显著降低 DOM 数量与首帧开销。两个配套参数height菜单高度px默认204item-size节点行高px默认34。对应常量定义于 config.tsexport const CASCADER_PANEL_ITEM_SIZE 34 export const CASCADER_PANEL_HEIGHT 204el-cascader :optionsoptions virtual-scroll :height300 :item-size34 /若数据量不大保持默认false即可避免不必要的开销。示例见 virtual-scroll.vue。十三、搜索建议面板宽度fit-input-width2.14.0过滤模式下建议面板suggestion panel的宽度默认按匹配项的最大宽度动态计算。但若通过suggestion-item插槽自定义了建议项内容其实际渲染文本很可能与label值不一致导致宽度计算错误。此时可设置fit-input-width值为true建议面板宽度与输入框等宽值为数字建议面板宽度固定为该像素值默认false按内容自动计算。官方文档特别提示fit-input-width只影响搜索时的建议面板宽度不影响默认级联面板的宽度。示例见 fit-input-width.vue。十四、Cascader 完整 API以下 API 表完整继承自官方文档 cascader.md并在源码处标明了默认值出处。14.1 Cascader Attributes名称说明类型默认值model-value / v-model绑定值string[] \| number[] \| any—options选项数据value/label键名可由CascaderProps定制CascaderOption[][]props配置项见下方 CascaderProps 表CascaderProps{}size输入框尺寸large \| default \| small—placeholder输入框占位文本string—disabled是否禁用boolean—clearable是否可清空选中值boolean—clear-icon ^(2.11.0)自定义清空图标组件string \| ComponentCircleCloseshow-all-levels输入框是否展示选中值的完整路径booleantruecollapse-tags多选模式下是否折叠标签boolean—collapse-tags-tooltip悬停折叠文本时是否展示全部标签需collapse-tags truebooleanfalsemax-collapse-tags-tooltip-height ^(2.10.2)折叠标签 Tooltip 最大高度string \| number—separator选项 label 分隔符string / filterable是否可搜索boolean—filter-method自定义搜索逻辑返回布尔值表示是否命中(node, keyword) booleannode.text.includes(keyword)debounce搜索防抖延迟毫秒number300before-filter过滤前钩子返回false或 rejected Promise 时中止过滤(value: string) boolean() truepopper-class下拉与标签 Tooltip 的自定义类名stringpopper-style下拉与标签 Tooltip 的自定义样式string \| object—teleported弹层是否 teleport 到 bodybooleantrueeffect ^(2.10.5)Tooltip 主题dark \| lightlighttag-type标签类型success \| info \| warning \| dangerinfotag-effect ^(2.7.8)标签效果light \| dark \| plainlightvalidate-event是否触发表单校验booleantruemax-collapse-tags ^(2.3.10)折叠时最多展示的标签数需collapse-tags truenumber1empty-values ^(2.7.0)组件的空值定义见 config-providerarray—value-on-clear ^(2.7.0)清空后的返回值见 config-providerstring \| number \| boolean \| Function—persistent ^(2.7.8)下拉失活且为false时是否销毁下拉booleantruefallback-placements ^(2.8.1)弹层翻转时的候选位置列表Placement[][bottom-start,bottom,top-start,top,right,left]placement ^(2.8.1)下拉位置top \| top-start \| ... \| right-end等 12 种bottom-startpopper-append-to-body ^(已废弃)是否将弹层追加到 body定位异常时可设false尝试booleantrueshow-checked-strategy ^(2.10.5)多选展示策略parent整洁/child每个子项都重要parent \| childchildvirtual-scroll ^(2.14.0)大数据量下是否开启虚拟滚动booleanfalsefit-input-width ^(2.14.0)建议面板宽度是否等于输入框数字时固定像素宽度boolean \| numberfalseitem-size ^(2.14.0)虚拟滚动节点行高pxnumber34height ^(2.14.0)虚拟滚动菜单高度pxnumber20414.2 Cascader Events名称说明类型change绑定值变化时触发(value: CascaderValue) voidexpand-change展开的选项变化时触发(value: CascaderValue) voidblur失焦时触发(event: FocusEvent) voidfocus聚焦时触发(event: FocusEvent) voidclear ^(2.7.7)点击清空图标时触发() voidvisible-change下拉显示/隐藏时触发(value: boolean) voidremove-tag多选模式下移除标签时触发(value) void14.3 Cascader Slots名称说明作用域default自定义级联节点内容{ node, data }empty无匹配选项时的内容—prefix ^(2.9.4)输入框前缀内容—suggestion-item ^(2.9.5)搜索建议项自定义内容{ item: CascaderNode }tag ^(2.10.3)自定义多选标签{ data, deleteTag }header ^(2.10.5)下拉顶部内容—footer ^(2.10.5)下拉底部内容—14.4 Cascader Exposes名称说明类型getCheckedNodes获取当前选中节点数组leafOnly为true时仅返回叶子节点默认false(leafOnly?: boolean) CascaderNode[] \| undefinedcascaderPanelRef级联面板 refComputedRefanytogglePopperVisible ^(2.2.31)切换弹层显隐(visible?: boolean) voidcontentRef级联内容区 refComputedRefanypresentText ^(2.8.4)当前选中内容的展示文本ComputedRefstringfocus ^(2.11.8)聚焦输入框() voidblur ^(2.11.8)使输入框失焦() void十五、CascaderPanel API15.1 CascaderPanel Attributes名称说明类型默认值model-value / v-model绑定值string[] \| number[] \| any—options选项数据CascaderOption[][]props配置项CascaderProps{}virtual-scroll ^(2.14.0)是否开启虚拟滚动booleanfalseitem-size ^(2.14.0)虚拟滚动节点行高pxnumber34height ^(2.14.0)虚拟滚动菜单高度pxnumber20415.2 CascaderPanel Events名称说明类型change绑定值变化时触发(value: CascaderValue \| undefined) voidupdate:modelValue绑定值变化时触发(value: CascaderValue \| undefined) voidexpand-change展开选项变化时触发(value: CascaderNodePathValue) voidclose关闭面板事件供 Cascader 收起面板判断() void15.3 CascaderPanel Slots名称说明作用域default自定义节点内容{ node, data }empty ^(2.8.3)无数据时的面板内容—15.4 CascaderPanel Exposes名称说明类型getCheckedNodes获取选中节点数组(leafOnly?: boolean) CascaderNode[] \| undefinedclearCheckedNodes清空选中节点() void十六、CascaderProps 配置详解props对象统一控制级联树的行为语义与组件外壳属性输入框、弹层相关分离。其默认值集中定义在 DefaultProps并在运行时与用户传入的props合并export const useCascaderConfig (props: { props: CascaderProps }) { return computed(() ({ ...DefaultProps, ...props.props, })) }属性说明类型默认值expandTrigger展开子选项的触发方式click \| hoverclickmultiple是否开启多选booleanfalsecheckStrictly节点勾选状态是否不影响父/子节点booleanfalseemitPath选中变化时是否发出节点路径数组false时仅发出节点自身的值booleantruelazy是否动态加载子节点需配合lazyLoadbooleanfalselazyLoad加载子节点数据的方法仅lazy true时生效2.11.5 支持reject参数(node, resolve, reject) void—value指定节点对象中用作值的键名stringvaluelabel指定节点对象中用作展示文本的键名stringlabelchildren指定节点对象中子节点的键名stringchildrendisabled指定节点对象中禁用标记的键名也支持函数string \| (data, node) booleandisabledleaf指定节点对象中叶子标记的键名也支持函数string \| (data, node) booleanleafhoverThresholdhover 展开的悬停阈值毫秒number500checkOnClickNode ^(2.10.5)点击节点时是否勾选/取消勾选booleanfalsecheckOnClickLeaf ^(2.10.5)点击叶子节点时是否勾选/取消勾选booleantrueshowPrefix ^(2.10.5)是否显示 radio/checkbox 前缀图标booleantrue其中emitPath直接决定v-model绑定值的形式为true默认时绑定的是路径值数组为false时只绑定当前选中节点的value。对应实现见 Node.valueByOptionget valueByOption() { return this.config.emitPath ? this.pathValues : this.value }十七、类型声明与 Node 节点模型官方文档末尾给出了完整的 TypeScript 声明见 cascader.md 的 Type Declarations 小节核心类型在源码 types.ts 中同样可见type CascaderNodeValue string | number | Recordstring, any type CascaderNodePathValue CascaderNodeValue[] type CascaderValue | CascaderNodeValue | CascaderNodePathValue | (CascaderNodeValue | CascaderNodePathValue)[] type Resolve (data: any) void type ExpandTrigger click | hover type LazyLoad (node: Node, resolve: Resolve, reject: () void) void type isDisabled (data: CascaderOption, node: Node) boolean type isLeaf (data: CascaderOption, node: Node) boolean interface CascaderOption extends Recordstring, unknown { label?: string value?: CascaderNodeValue children?: CascaderOption[] disabled?: boolean leaf?: boolean } interface CascaderProps { expandTrigger?: ExpandTrigger multiple?: boolean checkStrictly?: boolean emitPath?: boolean lazy?: boolean lazyLoad?: LazyLoad value?: string label?: string children?: string disabled?: string | isDisabled leaf?: string | isLeaf hoverThreshold?: number }树节点模型Node即公开类型CascaderNode的完整结构定义在 node.ts 中理解它有助于掌握组件的内部运行机制只读元数据uid全局自增唯一 id、level层级根节点为 1、value、label、pathNodes/pathValues/pathLabels从根到当前节点的完整路径状态字段checked是否勾选、indeterminate半选状态、loading动态加载中、loaded子数据是否已加载派生属性isDisabled自身及父链禁用判定、isLeaf叶子判定、valueByOption按emitPath决定取值形式核心方法calcText(allLevels, separator)计算展示文本、broadcast/emit/onParentCheck/onChildCheck/setCheckState/doCheck父子勾选联动与半选计算。这套节点模型将数据与状态解耦options是静态数据Node负责在运行时维护勾选、加载、展开等交互状态这也是getCheckedNodes、presentText等暴露方法能即时反映当前状态的根本原因。十八、实战小结按场景选择配置省市区/组织架构单选options 默认配置即可必要时props.emitPath false简化绑定值多选且值很多props.multiple truecollapse-tagsmax-collapse-tagscollapse-tags-tooltip追求整洁可加show-checked-strategyparent父子层级可选props.checkStrictly true配合checkOnClickNode提升点击体验服务端按需加载props.lazy trueprops.lazyLoad用leaf字段声明叶子大数据量virtual-scroll 按需调整height/item-size需要完全自定义弹层内容default、tag、header、footer、suggestion-item插槽组合使用。文中所有演示均可在仓库的 docs/examples/cascader 目录找到对应的可运行示例源码级默认值可查阅 cascader.ts、config.ts 与 node.ts。【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价