Cascader 级联选择器
当选项具有清晰的层级结构时,可使用级联选择器进行查看与选择。
基础用法
展开子级选项有两种触发方式。
将 options 绑定为选项数组即可渲染级联选择器。props.expandTrigger 用于定义子级如何展开。
Child options expand when clicked (default)
Child options expand when hovered
<template>
<div class="m-4">
<p>Child options expand when clicked (default)</p>
<u-cascader v-model="value" :options="options" @change="handleChange" />
</div>
<div class="m-4">
<p>Child options expand when hovered</p>
<u-cascader
v-model="value"
:options="options"
:props="props"
@change="handleChange"
/>
</div>
</template>
<script lang="ts" 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',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
{
value: 'top nav',
label: 'Top Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
{
value: 'color',
label: 'Color',
},
{
value: 'typography',
label: 'Typography',
},
{
value: 'icon',
label: 'Icon',
},
{
value: 'button',
label: 'Button',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
{
value: 'checkbox',
label: 'Checkbox',
},
{
value: 'input',
label: 'Input',
},
{
value: 'input-number',
label: 'InputNumber',
},
{
value: 'select',
label: 'Select',
},
{
value: 'cascader',
label: 'Cascader',
},
{
value: 'switch',
label: 'Switch',
},
{
value: 'slider',
label: 'Slider',
},
{
value: 'time-picker',
label: 'TimePicker',
},
{
value: 'date-picker',
label: 'DatePicker',
},
{
value: 'datetime-picker',
label: 'DateTimePicker',
},
{
value: 'upload',
label: 'Upload',
},
{
value: 'rate',
label: 'Rate',
},
{
value: 'form',
label: 'Form',
},
],
},
{
value: 'data',
label: 'Data',
children: [
{
value: 'table',
label: 'Table',
},
{
value: 'tag',
label: 'Tag',
},
{
value: 'progress',
label: 'Progress',
},
{
value: 'tree',
label: 'Tree',
},
{
value: 'pagination',
label: 'Pagination',
},
{
value: 'badge',
label: 'Badge',
},
],
},
{
value: 'notice',
label: 'Notice',
children: [
{
value: 'alert',
label: 'Alert',
},
{
value: 'loading',
label: 'Loading',
},
{
value: 'message',
label: 'Message',
},
{
value: 'message-box',
label: 'MessageBox',
},
{
value: 'notification',
label: 'Notification',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'menu',
label: 'Menu',
},
{
value: 'tabs',
label: 'Tabs',
},
{
value: 'breadcrumb',
label: 'Breadcrumb',
},
{
value: 'dropdown',
label: 'Dropdown',
},
{
value: 'steps',
label: 'Steps',
},
],
},
{
value: 'others',
label: 'Others',
children: [
{
value: 'dialog',
label: 'Dialog',
},
{
value: 'tooltip',
label: 'Tooltip',
},
{
value: 'popover',
label: 'Popover',
},
{
value: 'card',
label: 'Card',
},
{
value: 'carousel',
label: 'Carousel',
},
{
value: 'collapse',
label: 'Collapse',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
{
value: 'sketch',
label: 'Sketch Templates',
},
{
value: 'docs',
label: 'Design Documentation',
},
],
},
]
</script>
禁用选项
在选项对象中设置 disabled 字段即可禁用该项。
本例 options 首项包含 disabled: true,因此禁用。默认读取每项的 disabled 字段;若使用其他字段表示禁用,可在 props.disabled 中映射(详见下方 API)。value、label、children 字段名同样支持自定义。
<template>
<u-cascader :options="options" />
</template>
<script lang="ts" setup>
const options = [
{
value: 'guide',
label: 'Guide',
disabled: true,
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',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
{
value: 'top nav',
label: 'Top Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
{
value: 'color',
label: 'Color',
},
{
value: 'typography',
label: 'Typography',
},
{
value: 'icon',
label: 'Icon',
},
{
value: 'button',
label: 'Button',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
{
value: 'checkbox',
label: 'Checkbox',
},
{
value: 'input',
label: 'Input',
},
{
value: 'input-number',
label: 'InputNumber',
},
{
value: 'select',
label: 'Select',
},
{
value: 'cascader',
label: 'Cascader',
},
{
value: 'switch',
label: 'Switch',
},
{
value: 'slider',
label: 'Slider',
},
{
value: 'time-picker',
label: 'TimePicker',
},
{
value: 'date-picker',
label: 'DatePicker',
},
{
value: 'datetime-picker',
label: 'DateTimePicker',
},
{
value: 'upload',
label: 'Upload',
},
{
value: 'rate',
label: 'Rate',
},
{
value: 'form',
label: 'Form',
},
],
},
{
value: 'data',
label: 'Data',
children: [
{
value: 'table',
label: 'Table',
},
{
value: 'tag',
label: 'Tag',
},
{
value: 'progress',
label: 'Progress',
},
{
value: 'tree',
label: 'Tree',
},
{
value: 'pagination',
label: 'Pagination',
},
{
value: 'badge',
label: 'Badge',
},
],
},
{
value: 'notice',
label: 'Notice',
children: [
{
value: 'alert',
label: 'Alert',
},
{
value: 'loading',
label: 'Loading',
},
{
value: 'message',
label: 'Message',
},
{
value: 'message-box',
label: 'MessageBox',
},
{
value: 'notification',
label: 'Notification',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'menu',
label: 'Menu',
},
{
value: 'tabs',
label: 'Tabs',
},
{
value: 'breadcrumb',
label: 'Breadcrumb',
},
{
value: 'dropdown',
label: 'Dropdown',
},
{
value: 'steps',
label: 'Steps',
},
],
},
{
value: 'others',
label: 'Others',
children: [
{
value: 'dialog',
label: 'Dialog',
},
{
value: 'tooltip',
label: 'Tooltip',
},
{
value: 'popover',
label: 'Popover',
},
{
value: 'card',
label: 'Card',
},
{
value: 'carousel',
label: 'Carousel',
},
{
value: 'collapse',
label: 'Collapse',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
{
value: 'sketch',
label: 'Sketch Templates',
},
{
value: 'docs',
label: 'Design Documentation',
},
],
},
]
</script>
可清空
为 el-cascader 设置 clearable 后,选中并悬停时会显示清空图标。
<template>
<u-cascader :options="options" clearable />
</template>
<script lang="ts" setup>
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',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
{
value: 'top nav',
label: 'Top Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
{
value: 'color',
label: 'Color',
},
{
value: 'typography',
label: 'Typography',
},
{
value: 'icon',
label: 'Icon',
},
{
value: 'button',
label: 'Button',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
{
value: 'checkbox',
label: 'Checkbox',
},
{
value: 'input',
label: 'Input',
},
{
value: 'input-number',
label: 'InputNumber',
},
{
value: 'select',
label: 'Select',
},
{
value: 'cascader',
label: 'Cascader',
},
{
value: 'switch',
label: 'Switch',
},
{
value: 'slider',
label: 'Slider',
},
{
value: 'time-picker',
label: 'TimePicker',
},
{
value: 'date-picker',
label: 'DatePicker',
},
{
value: 'datetime-picker',
label: 'DateTimePicker',
},
{
value: 'upload',
label: 'Upload',
},
{
value: 'rate',
label: 'Rate',
},
{
value: 'form',
label: 'Form',
},
],
},
{
value: 'data',
label: 'Data',
children: [
{
value: 'table',
label: 'Table',
},
{
value: 'tag',
label: 'Tag',
},
{
value: 'progress',
label: 'Progress',
},
{
value: 'tree',
label: 'Tree',
},
{
value: 'pagination',
label: 'Pagination',
},
{
value: 'badge',
label: 'Badge',
},
],
},
{
value: 'notice',
label: 'Notice',
children: [
{
value: 'alert',
label: 'Alert',
},
{
value: 'loading',
label: 'Loading',
},
{
value: 'message',
label: 'Message',
},
{
value: 'message-box',
label: 'MessageBox',
},
{
value: 'notification',
label: 'Notification',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'menu',
label: 'Menu',
},
{
value: 'tabs',
label: 'Tabs',
},
{
value: 'breadcrumb',
label: 'Breadcrumb',
},
{
value: 'dropdown',
label: 'Dropdown',
},
{
value: 'steps',
label: 'Steps',
},
],
},
{
value: 'others',
label: 'Others',
children: [
{
value: 'dialog',
label: 'Dialog',
},
{
value: 'tooltip',
label: 'Tooltip',
},
{
value: 'popover',
label: 'Popover',
},
{
value: 'card',
label: 'Card',
},
{
value: 'carousel',
label: 'Carousel',
},
{
value: 'collapse',
label: 'Collapse',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
{
value: 'sketch',
label: 'Sketch Templates',
},
{
value: 'docs',
label: 'Design Documentation',
},
],
},
]
</script>
自定义清空图标
通过 clear-icon 自定义清空图标。
<template>
<u-cascader
:options="options"
clearable
:clear-icon="CloseBold"
placeholder="Custom clear icon"
/>
</template>
<script lang="ts" setup>
import { CloseBold } from '@uniboot/icons-vue'
const options = [
{
value: 'guide',
label: 'Guide',
children: [
{
value: 'disciplines',
label: 'Disciplines',
},
],
},
]
</script>
仅显示最后一级
输入框可只展示最后一级,而非完整路径。
show-all-levels 控制是否展示所有层级;为 false 时仅展示最后一级。
<template>
<u-cascader :options="options" :show-all-levels="false" />
</template>
<script lang="ts" setup>
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',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
{
value: 'top nav',
label: 'Top Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
{
value: 'color',
label: 'Color',
},
{
value: 'typography',
label: 'Typography',
},
{
value: 'icon',
label: 'Icon',
},
{
value: 'button',
label: 'Button',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
{
value: 'checkbox',
label: 'Checkbox',
},
{
value: 'input',
label: 'Input',
},
{
value: 'input-number',
label: 'InputNumber',
},
{
value: 'select',
label: 'Select',
},
{
value: 'cascader',
label: 'Cascader',
},
{
value: 'switch',
label: 'Switch',
},
{
value: 'slider',
label: 'Slider',
},
{
value: 'time-picker',
label: 'TimePicker',
},
{
value: 'date-picker',
label: 'DatePicker',
},
{
value: 'datetime-picker',
label: 'DateTimePicker',
},
{
value: 'upload',
label: 'Upload',
},
{
value: 'rate',
label: 'Rate',
},
{
value: 'form',
label: 'Form',
},
],
},
{
value: 'data',
label: 'Data',
children: [
{
value: 'table',
label: 'Table',
},
{
value: 'tag',
label: 'Tag',
},
{
value: 'progress',
label: 'Progress',
},
{
value: 'tree',
label: 'Tree',
},
{
value: 'pagination',
label: 'Pagination',
},
{
value: 'badge',
label: 'Badge',
},
],
},
{
value: 'notice',
label: 'Notice',
children: [
{
value: 'alert',
label: 'Alert',
},
{
value: 'loading',
label: 'Loading',
},
{
value: 'message',
label: 'Message',
},
{
value: 'message-box',
label: 'MessageBox',
},
{
value: 'notification',
label: 'Notification',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'menu',
label: 'Menu',
},
{
value: 'tabs',
label: 'Tabs',
},
{
value: 'breadcrumb',
label: 'Breadcrumb',
},
{
value: 'dropdown',
label: 'Dropdown',
},
{
value: 'steps',
label: 'Steps',
},
],
},
{
value: 'others',
label: 'Others',
children: [
{
value: 'dialog',
label: 'Dialog',
},
{
value: 'tooltip',
label: 'Tooltip',
},
{
value: 'popover',
label: 'Popover',
},
{
value: 'card',
label: 'Card',
},
{
value: 'carousel',
label: 'Carousel',
},
{
value: 'collapse',
label: 'Collapse',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
{
value: 'sketch',
label: 'Sketch Templates',
},
{
value: 'docs',
label: 'Design Documentation',
},
],
},
]
</script>
多选
在标签上使用 :props="props",并在脚本中 const props = { multiple: true }。
推荐写法:
<template>
<u-cascader :props="props" />
</template>
<script lang="ts" setup>
const props = { multiple: true }
</script>不推荐:
<template>
<!-- 级联选择器此处使用对象字面量绑定无效 -->
<u-cascader :props="{ multiple: true }" />
</template>多选时默认展示全部标签;collapse-tags 为 true 可折叠;max-collapse-tags 控制最多展示数量,默认 1。collapse-tags-tooltip 可在悬停折叠文案时查看全部选中项。
Display all tags (default)
Collapse tags
Collapse tags tooltip
Max Collapse Tags
<template>
<div class="m-4">
<p>Display all tags (default)</p>
<u-cascader :options="options" :props="props" clearable />
</div>
<div class="m-4">
<p>Collapse tags</p>
<u-cascader :options="options" :props="props" collapse-tags clearable />
</div>
<div class="m-4">
<p>Collapse tags tooltip</p>
<u-cascader
:options="options"
:props="props"
collapse-tags
collapse-tags-tooltip
clearable
/>
</div>
<div class="m-4">
<p>Max Collapse Tags</p>
<u-cascader
:options="options"
:props="props"
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="3"
clearable
/>
</div>
</template>
<script lang="ts" setup>
const props = { multiple: true }
const options = [
{
value: 1,
label: 'Asia',
children: [
{
value: 2,
label: 'China',
children: [
{ value: 3, label: 'Beijing' },
{ value: 4, label: 'Shanghai' },
{ value: 5, label: 'Hangzhou' },
],
},
{
value: 6,
label: 'Japan',
children: [
{ value: 7, label: 'Tokyo' },
{ value: 8, label: 'Osaka' },
{ value: 9, label: 'Kyoto' },
],
},
{
value: 10,
label: 'Korea',
children: [
{ value: 11, label: 'Seoul' },
{ value: 12, label: 'Busan' },
{ value: 13, label: 'Taegu' },
],
},
],
},
{
value: 14,
label: 'Europe',
children: [
{
value: 15,
label: 'France',
children: [
{ value: 16, label: 'Paris' },
{ value: 17, label: 'Marseille' },
{ value: 18, label: 'Lyon' },
],
},
{
value: 19,
label: 'UK',
children: [
{ value: 20, label: 'London' },
{ value: 21, label: 'Birmingham' },
{ value: 22, label: 'Manchester' },
],
},
],
},
{
value: 23,
label: 'North America',
children: [
{
value: 24,
label: 'US',
children: [
{ value: 25, label: 'New York' },
{ value: 26, label: 'Los Angeles' },
{ value: 27, label: 'Washington' },
],
},
{
value: 28,
label: 'Canada',
children: [
{ value: 29, label: 'Toronto' },
{ value: 30, label: 'Montreal' },
{ value: 31, label: 'Ottawa' },
],
},
],
},
]
</script>
选择任意一级
单选时默认只能选叶子节点;多选时勾选父级会联动子级。开启本能力后父子选中状态可解耦,从而选择任意一级。
设置 props.checkStrictly = true,节点选中状态不再影响父子,即可选择任意层级。
Select any level of options (Single selection)
Select any level of options (Multiple selection)
<template>
<div class="m-4">
<p>Select any level of options (Single selection)</p>
<u-cascader :options="options" :props="props1" clearable />
</div>
<div class="m-4">
<p>Select any level of options (Multiple selection)</p>
<u-cascader :options="options" :props="props2" clearable />
</div>
</template>
<script lang="ts" setup>
const props1 = {
checkStrictly: true,
}
const props2 = {
multiple: true,
checkStrictly: true,
}
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',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
{
value: 'top nav',
label: 'Top Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
{
value: 'color',
label: 'Color',
},
{
value: 'typography',
label: 'Typography',
},
{
value: 'icon',
label: 'Icon',
},
{
value: 'button',
label: 'Button',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
{
value: 'checkbox',
label: 'Checkbox',
},
{
value: 'input',
label: 'Input',
},
{
value: 'input-number',
label: 'InputNumber',
},
{
value: 'select',
label: 'Select',
},
{
value: 'cascader',
label: 'Cascader',
},
{
value: 'switch',
label: 'Switch',
},
{
value: 'slider',
label: 'Slider',
},
{
value: 'time-picker',
label: 'TimePicker',
},
{
value: 'date-picker',
label: 'DatePicker',
},
{
value: 'datetime-picker',
label: 'DateTimePicker',
},
{
value: 'upload',
label: 'Upload',
},
{
value: 'rate',
label: 'Rate',
},
{
value: 'form',
label: 'Form',
},
],
},
{
value: 'data',
label: 'Data',
children: [
{
value: 'table',
label: 'Table',
},
{
value: 'tag',
label: 'Tag',
},
{
value: 'progress',
label: 'Progress',
},
{
value: 'tree',
label: 'Tree',
},
{
value: 'pagination',
label: 'Pagination',
},
{
value: 'badge',
label: 'Badge',
},
],
},
{
value: 'notice',
label: 'Notice',
children: [
{
value: 'alert',
label: 'Alert',
},
{
value: 'loading',
label: 'Loading',
},
{
value: 'message',
label: 'Message',
},
{
value: 'message-box',
label: 'MessageBox',
},
{
value: 'notification',
label: 'Notification',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'menu',
label: 'Menu',
},
{
value: 'tabs',
label: 'Tabs',
},
{
value: 'breadcrumb',
label: 'Breadcrumb',
},
{
value: 'dropdown',
label: 'Dropdown',
},
{
value: 'steps',
label: 'Steps',
},
],
},
{
value: 'others',
label: 'Others',
children: [
{
value: 'dialog',
label: 'Dialog',
},
{
value: 'tooltip',
label: 'Tooltip',
},
{
value: 'popover',
label: 'Popover',
},
{
value: 'card',
label: 'Card',
},
{
value: 'carousel',
label: 'Carousel',
},
{
value: 'collapse',
label: 'Collapse',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
{
value: 'sketch',
label: 'Sketch Templates',
},
{
value: 'docs',
label: 'Design Documentation',
},
],
},
]
</script>
动态加载
点击节点时动态加载子级。
设置 lazy = true 启用动态加载,并通过 lazyLoad 定义如何加载数据。lazyLoad 第一个参数为当前节点 node,第二个 resolve 为加载完成回调(必须调用)。为准确展示节点状态,可增加 leaf 字段(或通过 props.leaf 映射)表示是否为叶子节点;否则将根据是否存在子节点推断。
<template>
<u-cascader :props="props" />
</template>
<script lang="ts" setup>
import type { CascaderProps } from 'uniboot-ui'
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>
可搜索
通过关键字搜索并选择选项。
为 el-cascader 增加 filterable 开启过滤。默认会匹配标签或其父级标签(取决于 show-all-levels)是否包含关键字。也可通过 filter-method 自定义:第一个参数为 node,第二个为 keyword,返回布尔值表示是否命中。
Filterable (Single selection)
Filterable (Multiple selection)
<template>
<div class="m-4">
<p>Filterable (Single selection)</p>
<u-cascader
placeholder="Try searchingL Guide"
:options="options"
filterable
/>
</div>
<div class="m-4">
<p>Filterable (Multiple selection)</p>
<u-cascader
placeholder="Try searchingL Guide"
:options="options"
:props="props"
filterable
/>
</div>
</template>
<script lang="ts" setup>
const props = {
multiple: true,
}
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',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
{
value: 'top nav',
label: 'Top Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
{
value: 'color',
label: 'Color',
},
{
value: 'typography',
label: 'Typography',
},
{
value: 'icon',
label: 'Icon',
},
{
value: 'button',
label: 'Button',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
{
value: 'checkbox',
label: 'Checkbox',
},
{
value: 'input',
label: 'Input',
},
{
value: 'input-number',
label: 'InputNumber',
},
{
value: 'select',
label: 'Select',
},
{
value: 'cascader',
label: 'Cascader',
},
{
value: 'switch',
label: 'Switch',
},
{
value: 'slider',
label: 'Slider',
},
{
value: 'time-picker',
label: 'TimePicker',
},
{
value: 'date-picker',
label: 'DatePicker',
},
{
value: 'datetime-picker',
label: 'DateTimePicker',
},
{
value: 'upload',
label: 'Upload',
},
{
value: 'rate',
label: 'Rate',
},
{
value: 'form',
label: 'Form',
},
],
},
{
value: 'data',
label: 'Data',
children: [
{
value: 'table',
label: 'Table',
},
{
value: 'tag',
label: 'Tag',
},
{
value: 'progress',
label: 'Progress',
},
{
value: 'tree',
label: 'Tree',
},
{
value: 'pagination',
label: 'Pagination',
},
{
value: 'badge',
label: 'Badge',
},
],
},
{
value: 'notice',
label: 'Notice',
children: [
{
value: 'alert',
label: 'Alert',
},
{
value: 'loading',
label: 'Loading',
},
{
value: 'message',
label: 'Message',
},
{
value: 'message-box',
label: 'MessageBox',
},
{
value: 'notification',
label: 'Notification',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'menu',
label: 'Menu',
},
{
value: 'tabs',
label: 'Tabs',
},
{
value: 'breadcrumb',
label: 'Breadcrumb',
},
{
value: 'dropdown',
label: 'Dropdown',
},
{
value: 'steps',
label: 'Steps',
},
],
},
{
value: 'others',
label: 'Others',
children: [
{
value: 'dialog',
label: 'Dialog',
},
{
value: 'tooltip',
label: 'Tooltip',
},
{
value: 'popover',
label: 'Popover',
},
{
value: 'card',
label: 'Card',
},
{
value: 'carousel',
label: 'Carousel',
},
{
value: 'collapse',
label: 'Collapse',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
{
value: 'sketch',
label: 'Sketch Templates',
},
{
value: 'docs',
label: 'Design Documentation',
},
],
},
]
</script>
自定义节点内容
可自定义级联节点展示内容。
使用作用域插槽自定义节点;作用域提供 node(节点对象)与 data(节点数据)。
<template>
<u-cascader :options="options">
<template #default="{ node, data }">
<span>{{ data.label }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</u-cascader>
</template>
<script lang="ts" setup>
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',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
{
value: 'top nav',
label: 'Top Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
{
value: 'color',
label: 'Color',
},
{
value: 'typography',
label: 'Typography',
},
{
value: 'icon',
label: 'Icon',
},
{
value: 'button',
label: 'Button',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
{
value: 'checkbox',
label: 'Checkbox',
},
{
value: 'input',
label: 'Input',
},
{
value: 'input-number',
label: 'InputNumber',
},
{
value: 'select',
label: 'Select',
},
{
value: 'cascader',
label: 'Cascader',
},
{
value: 'switch',
label: 'Switch',
},
{
value: 'slider',
label: 'Slider',
},
{
value: 'time-picker',
label: 'TimePicker',
},
{
value: 'date-picker',
label: 'DatePicker',
},
{
value: 'datetime-picker',
label: 'DateTimePicker',
},
{
value: 'upload',
label: 'Upload',
},
{
value: 'rate',
label: 'Rate',
},
{
value: 'form',
label: 'Form',
},
],
},
{
value: 'data',
label: 'Data',
children: [
{
value: 'table',
label: 'Table',
},
{
value: 'tag',
label: 'Tag',
},
{
value: 'progress',
label: 'Progress',
},
{
value: 'tree',
label: 'Tree',
},
{
value: 'pagination',
label: 'Pagination',
},
{
value: 'badge',
label: 'Badge',
},
],
},
{
value: 'notice',
label: 'Notice',
children: [
{
value: 'alert',
label: 'Alert',
},
{
value: 'loading',
label: 'Loading',
},
{
value: 'message',
label: 'Message',
},
{
value: 'message-box',
label: 'MessageBox',
},
{
value: 'notification',
label: 'Notification',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'menu',
label: 'Menu',
},
{
value: 'tabs',
label: 'Tabs',
},
{
value: 'breadcrumb',
label: 'Breadcrumb',
},
{
value: 'dropdown',
label: 'Dropdown',
},
{
value: 'steps',
label: 'Steps',
},
],
},
{
value: 'others',
label: 'Others',
children: [
{
value: 'dialog',
label: 'Dialog',
},
{
value: 'tooltip',
label: 'Tooltip',
},
{
value: 'popover',
label: 'Popover',
},
{
value: 'card',
label: 'Card',
},
{
value: 'carousel',
label: 'Carousel',
},
{
value: 'collapse',
label: 'Collapse',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
{
value: 'sketch',
label: 'Sketch Templates',
},
{
value: 'docs',
label: 'Design Documentation',
},
],
},
]
</script>
自定义搜索项
通过 suggestion-item 插槽自定义过滤建议项;作用域提供 item。
<template>
<u-cascader :options="options" filterable placeholder="Try searching: Guide">
<template #suggestion-item="{ item }">
<span>🔍 {{ item.pathLabels.join(' > ') }}</span>
</template>
</u-cascader>
</template>
<script lang="ts" setup>
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',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
{
value: 'top nav',
label: 'Top Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
{
value: 'color',
label: 'Color',
},
{
value: 'typography',
label: 'Typography',
},
{
value: 'icon',
label: 'Icon',
},
{
value: 'button',
label: 'Button',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
{
value: 'checkbox',
label: 'Checkbox',
},
{
value: 'input',
label: 'Input',
},
{
value: 'input-number',
label: 'InputNumber',
},
{
value: 'select',
label: 'Select',
},
{
value: 'cascader',
label: 'Cascader',
},
{
value: 'switch',
label: 'Switch',
},
{
value: 'slider',
label: 'Slider',
},
{
value: 'time-picker',
label: 'TimePicker',
},
{
value: 'date-picker',
label: 'DatePicker',
},
{
value: 'datetime-picker',
label: 'DateTimePicker',
},
{
value: 'upload',
label: 'Upload',
},
{
value: 'rate',
label: 'Rate',
},
{
value: 'form',
label: 'Form',
},
],
},
{
value: 'data',
label: 'Data',
children: [
{
value: 'table',
label: 'Table',
},
{
value: 'tag',
label: 'Tag',
},
{
value: 'progress',
label: 'Progress',
},
{
value: 'tree',
label: 'Tree',
},
{
value: 'pagination',
label: 'Pagination',
},
{
value: 'badge',
label: 'Badge',
},
],
},
{
value: 'notice',
label: 'Notice',
children: [
{
value: 'alert',
label: 'Alert',
},
{
value: 'loading',
label: 'Loading',
},
{
value: 'message',
label: 'Message',
},
{
value: 'message-box',
label: 'MessageBox',
},
{
value: 'notification',
label: 'Notification',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'menu',
label: 'Menu',
},
{
value: 'tabs',
label: 'Tabs',
},
{
value: 'breadcrumb',
label: 'Breadcrumb',
},
{
value: 'dropdown',
label: 'Dropdown',
},
{
value: 'steps',
label: 'Steps',
},
],
},
{
value: 'others',
label: 'Others',
children: [
{
value: 'dialog',
label: 'Dialog',
},
{
value: 'tooltip',
label: 'Tooltip',
},
{
value: 'popover',
label: 'Popover',
},
{
value: 'card',
label: 'Card',
},
{
value: 'carousel',
label: 'Carousel',
},
{
value: 'collapse',
label: 'Collapse',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
{
value: 'sketch',
label: 'Sketch Templates',
},
{
value: 'docs',
label: 'Design Documentation',
},
],
},
]
</script>
级联面板
CascaderPanel 是 Cascader 的核心子组件,支持单选、多选、动态加载等能力。
与 el-cascader 类似,通过 options 设置数据,通过 props 启用特性,详见下方 API。
- Guide
- Component
- Resource
<template>
<u-cascader-panel :options="options" />
</template>
<script lang="ts" setup>
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',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
{
value: 'top nav',
label: 'Top Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
{
value: 'color',
label: 'Color',
},
{
value: 'typography',
label: 'Typography',
},
{
value: 'icon',
label: 'Icon',
},
{
value: 'button',
label: 'Button',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
{
value: 'checkbox',
label: 'Checkbox',
},
{
value: 'input',
label: 'Input',
},
{
value: 'input-number',
label: 'InputNumber',
},
{
value: 'select',
label: 'Select',
},
{
value: 'cascader',
label: 'Cascader',
},
{
value: 'switch',
label: 'Switch',
},
{
value: 'slider',
label: 'Slider',
},
{
value: 'time-picker',
label: 'TimePicker',
},
{
value: 'date-picker',
label: 'DatePicker',
},
{
value: 'datetime-picker',
label: 'DateTimePicker',
},
{
value: 'upload',
label: 'Upload',
},
{
value: 'rate',
label: 'Rate',
},
{
value: 'form',
label: 'Form',
},
],
},
{
value: 'data',
label: 'Data',
children: [
{
value: 'table',
label: 'Table',
},
{
value: 'tag',
label: 'Tag',
},
{
value: 'progress',
label: 'Progress',
},
{
value: 'tree',
label: 'Tree',
},
{
value: 'pagination',
label: 'Pagination',
},
{
value: 'badge',
label: 'Badge',
},
],
},
{
value: 'notice',
label: 'Notice',
children: [
{
value: 'alert',
label: 'Alert',
},
{
value: 'loading',
label: 'Loading',
},
{
value: 'message',
label: 'Message',
},
{
value: 'message-box',
label: 'MessageBox',
},
{
value: 'notification',
label: 'Notification',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'menu',
label: 'Menu',
},
{
value: 'tabs',
label: 'Tabs',
},
{
value: 'breadcrumb',
label: 'Breadcrumb',
},
{
value: 'dropdown',
label: 'Dropdown',
},
{
value: 'steps',
label: 'Steps',
},
],
},
{
value: 'others',
label: 'Others',
children: [
{
value: 'dialog',
label: 'Dialog',
},
{
value: 'tooltip',
label: 'Tooltip',
},
{
value: 'popover',
label: 'Popover',
},
{
value: 'card',
label: 'Card',
},
{
value: 'carousel',
label: 'Carousel',
},
{
value: 'collapse',
label: 'Collapse',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
{
value: 'sketch',
label: 'Sketch Templates',
},
{
value: 'docs',
label: 'Design Documentation',
},
],
},
]
</script>
自定义标签
可自定义已选项标签。
在 el-cascader 的插槽中插入自定义标签时,collapse-tags、collapse-tags-tooltip、max-collapse-tags 将不生效。
Using slots allows for more flexible control over the display.
Display top-level tags only
<template>
<div class="m-4">
<p>Using slots allows for more flexible control over the display.</p>
<u-cascader :options="options" :props="props" clearable>
<template #tag="{ data }">
<u-tag
v-for="(item, index) in getTags(data)"
:key="item"
:color="index % 2 === 0 ? '#FFDE0A' : ''"
>
{{ item }}
</u-tag>
</template>
</u-cascader>
<p>Display top-level tags only</p>
<u-cascader :options="options" :props="props" clearable>
<template #tag="{ data }">
<u-tag v-for="item in getTopLevelTags(data)" :key="item">
{{ item }}
</u-tag>
</template>
</u-cascader>
</div>
</template>
<script lang="ts" setup>
import type { Tag } from 'uniboot-ui'
const props = { multiple: true }
const options = [
{
value: 1,
label: 'Asia',
children: [
{
value: 2,
label: 'China',
children: [
{ value: 3, label: 'Beijing' },
{ value: 4, label: 'Shanghai' },
{ value: 5, label: 'Hangzhou' },
],
},
{
value: 6,
label: 'Japan',
children: [
{ value: 7, label: 'Tokyo' },
{ value: 8, label: 'Osaka' },
{ value: 9, label: 'Kyoto' },
],
},
{
value: 10,
label: 'Korea',
children: [
{ value: 11, label: 'Seoul' },
{ value: 12, label: 'Busan' },
{ value: 13, label: 'Taegu' },
],
},
],
},
{
value: 14,
label: 'Europe',
children: [
{
value: 15,
label: 'France',
children: [
{ value: 16, label: 'Paris' },
{ value: 17, label: 'Marseille' },
{ value: 18, label: 'Lyon' },
],
},
{
value: 19,
label: 'UK',
children: [
{ value: 20, label: 'London' },
{ value: 21, label: 'Birmingham' },
{ value: 22, label: 'Manchester' },
],
},
],
},
{
value: 23,
label: 'North America',
children: [
{
value: 24,
label: 'US',
children: [
{ value: 25, label: 'New York' },
{ value: 26, label: 'Los Angeles' },
{ value: 27, label: 'Washington' },
],
},
{
value: 28,
label: 'Canada',
children: [
{ value: 29, label: 'Toronto' },
{ value: 30, label: 'Montreal' },
{ value: 31, label: 'Ottawa' },
],
},
],
},
]
const getTags = (data: Tag[]) => {
return data.map((item) => item.text)
}
const getTopLevelTags = (data: Tag[]) => {
const set: Set<string> = new Set()
for (const datum of data) {
let parent = datum.node?.parent
while (parent && parent.level !== 1) {
parent = parent.parent
}
const label = parent?.data?.label
label && set.add(label)
}
return [...set]
}
</script>
展示策略
控制多选模式下已选项的展示方式。
多选下使用 show-checked-strategy 控制展示:默认 child 展示所有选中子节点;parent 在子节点全部选中时仅展示父节点。
Strategy: child (default, show all selected child nodes)
Strategy: parent (show only parent nodes when all children are selected)
<template>
<div class="m-4">
<p>Strategy: child (default, show all selected child nodes)</p>
<u-cascader
v-model="value1"
:options="options"
:props="props"
show-checked-strategy="child"
clearable
@change="handleChange1"
/>
</div>
<div class="m-4">
<p>
Strategy: parent (show only parent nodes when all children are selected)
</p>
<u-cascader
v-model="value2"
:options="options"
:props="props"
show-checked-strategy="parent"
clearable
@change="handleChange2"
/>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const value1 = ref([])
const value2 = ref([])
const props = {
multiple: true,
}
const handleChange1 = (value) => {
console.log('Child strategy:', value)
}
const handleChange2 = (value) => {
console.log('Parent strategy:', value)
}
const options = [
{
value: 'guide',
label: 'Guide',
children: [
{
value: 'disciplines',
label: 'Disciplines',
children: [
{
value: 'consistency',
label: 'Consistency',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
],
},
]
</script>
点击节点选中
需配合 multiple 或 checkStrictly。
可设置 checkOnClickNode,在点击节点(除前缀图标外)时切换选中。使用 showPrefix 控制前缀显隐。
添加 checkOnClickLeaf 可仅在点击叶子(最后一级)时切换选中,默认开启。
checkStrictly | Single mode
Multiple mode
<template>
<div class="flex flex-col items-center">
<u-switch
v-model="showPrefix"
active-text="show prefix"
inactive-text="hide prefix"
/>
<div class="flex flex-wrap">
<div class="m-4">
<p>checkStrictly | Single mode</p>
<u-cascader
v-model="value"
:options="options"
:props="props1"
clearable
/>
</div>
<div class="m-4">
<p>Multiple mode</p>
<u-cascader
v-model="value2"
show-checked-strategy="parent"
:options="options"
:props="props2"
clearable
/>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
const value = ref()
const value2 = ref()
const showPrefix = ref(true)
const props1 = computed(() => ({
showPrefix: showPrefix.value,
checkStrictly: true,
checkOnClickNode: true,
}))
const props2 = computed(() => ({
showPrefix: showPrefix.value,
multiple: true,
checkOnClickNode: true,
}))
const options = [
{
value: 'guide',
label: 'Guide',
children: [
{
value: 'disciplines',
label: 'Disciplines',
children: [
{
value: 'consistency',
label: 'Consistency',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
],
},
],
},
{
value: 'component',
label: 'Component',
children: [
{
value: 'basic',
label: 'Basic',
children: [
{
value: 'layout',
label: 'Layout',
},
],
},
{
value: 'form',
label: 'Form',
children: [
{
value: 'radio',
label: 'Radio',
},
],
},
],
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
],
},
]
</script>
自定义头部与底部
可通过插槽自定义下拉面板的头部与底部。
使用插槽自定义内容。
Custom header content
Custom footer content
<template>
<div class="cascader-custom-header-footer">
<div>
<p>Custom header content</p>
<u-cascader
v-model="value"
popper-class="cascader-custom-header"
:options="options"
:props="props"
clearable
>
<template #header>
<u-checkbox
v-model="checkAll"
:indeterminate="indeterminate"
@change="handleCheckAll"
>
All
</u-checkbox>
</template>
</u-cascader>
</div>
<div>
<p>Custom footer content</p>
<u-cascader v-model="value" :options="options" :props="props" clearable>
<template #footer>
<u-button link size="small" @click="handleClear"> Clear </u-button>
</template>
</u-cascader>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import type { CascaderOption, CheckboxValueType } from 'uniboot-ui'
const props = { multiple: true }
const checkAll = ref(false)
const indeterminate = ref(false)
const value = ref<string[][]>([])
const options = ref([
{
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' },
],
},
],
},
])
const getAllValuePaths = computed(() => {
const result: string[][] = []
const queue: { node: CascaderOption; path: string[] }[] = options.value.map(
(node) => ({ node, path: [node.value] })
)
while (queue.length > 0) {
const { node, path } = queue.shift()!
if (node.children?.length) {
node.children.forEach((child) => {
queue.push({ node: child, path: [...path, child.value as string] })
})
} else {
result.push(path)
}
}
return result
})
watch(value, (val) => {
if (val.length === 0) {
checkAll.value = false
indeterminate.value = false
} else if (val.length === getAllValuePaths.value.length) {
checkAll.value = true
indeterminate.value = false
} else {
indeterminate.value = true
}
})
const handleCheckAll = (val: CheckboxValueType) => {
indeterminate.value = false
value.value = val ? getAllValuePaths.value : []
}
const handleClear = () => {
value.value = []
}
</script>
<style scoped>
.cascader-custom-header-footer {
display: flex;
}
.cascader-custom-header-footer > div {
flex: 1;
text-align: center;
}
.cascader-custom-header-footer > div:not(:last-child) {
border-right: 1px solid var(--u-border-color);
}
.cascader-custom-header .u-checkbox {
display: flex;
height: unset;
}
</style>
级联选择器 API
级联选择器 属性
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| model-value / v-model | 绑定值 | string / number /array | — |
| options | 选项数据;value、label 等键名可通过 CascaderProps 映射 | array | — |
| props | 配置项,见下方 CascaderProps 表 | object | — |
| size | 输入框尺寸 | enum | — |
| placeholder | 占位符 | string | — |
| disabled | 是否禁用 | boolean | — |
| clearable | 是否可清空 | boolean | — |
| clear-icon | 自定义清空图标 | string / object | CircleClose |
| show-all-levels | 输入框是否展示选中值的完整层级 | boolean | true |
| collapse-tags | 多选时是否折叠标签 | boolean | — |
| collapse-tags-tooltip | 悬停折叠文案时是否展示全部标签;需开启 collapse-tags | boolean | false |
| max-collapse-tags-tooltip-height | 折叠标签提示的最大高度 | string / number | — |
| separator | 选项分隔符 | string | ' / ' |
| filterable | 是否可搜索 | boolean | — |
| filter-method | 自定义搜索逻辑;参数为 node、keyword,返回是否命中 | Function | — |
| debounce | 搜索输入防抖(毫秒) | number | 300 |
| before-filter | 过滤前钩子,参数为待过滤字符串;返回 false 或 Promise 被拒绝则中止过滤 | Function | — |
| popper-class | 下拉与标签提示的自定义类名 | string | '' |
| popper-style | 下拉与标签提示的自定义样式 | string / object | — |
| teleported | 是否将弹出层传送至 body | boolean | true |
| effect | 标签提示主题,内置 dark / light | enum / string | light |
| tag-type | 标签类型 | enum | info |
| tag-effect | 标签效果 | enum | light |
| validate-event | 是否触发表单校验 | boolean | true |
| max-collapse-tags | 最多展示标签数;需开启 collapse-tags | number | 1 |
| empty-values | 空值配置,见 config-provider | array | — |
| value-on-clear | 清空时的返回值,见 config-provider | string / number / boolean / Function | — |
| persistent | 下拉失活且 persistent 为 false 时是否销毁下拉 | boolean | true |
| fallback-placements | Tooltip 可能位置列表 popper.js | array | — |
| placement | 下拉位置 | enum | bottom-start |
| show-checked-strategy | 多选下已选节点展示策略;需要层级更整洁用 parent,需要逐项展示用 child | enum | child |
级联选择器 事件
| 事件名 | 说明 | 类型 |
|---|---|---|
| change | 绑定值变化时 | Function |
| expand-change | 展开节点变化时 | Function |
| blur | 失焦时 | Function |
| focus | 聚焦时 | Function |
| clear | 可清空时点击清空图标 | Function |
| visible-change | 下拉出现/隐藏时 | Function |
| remove-tag | 多选移除标签时 | Function |
级联选择器 插槽
| 名称 | 说明 |
|---|---|
| default | 自定义节点内容;作用域为 node、data;作用域类型 ^[object]` |
| empty | 无匹配选项时的内容 |
| prefix | 输入框前缀内容 |
| suggestion-item | 搜索时自定义建议项;作用域类型 ^[object]` |
| tag | 自定义标签;作用域类型 ^[object]` |
| header | 下拉面板顶部内容 |
| footer | 下拉面板底部内容 |
级联选择器 暴露
| 名称 | 说明 | 类型 |
|---|---|---|
| getCheckedNodes | 获取当前选中节点数组;leafOnly 为 true 时仅返回叶子选中节点,默认 false | Function |
| cascaderPanelRef | 面板组件引用 | object |
| togglePopperVisible | 切换下拉显隐 | Function |
| contentRef | 内容区域引用 | object |
| presentText | 当前展示文本 | object |
| focus | 聚焦输入框 | Function |
| blur | 失焦输入框 | Function |
级联面板 API
级联面板 属性
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| model-value / v-model | 绑定值 | string/number/array | — |
| options | 选项数据;键名可通过 CascaderProps 映射 | array | — |
| props | 配置项,见 CascaderProps | object | — |
级联面板 事件
| 事件名 | 说明 | 类型 |
|---|---|---|
| change | 绑定值变化时 | Function |
| update:modelValue | 绑定值变化时 | Function |
| expand-change | 展开节点变化时 | Function |
| close | 关闭面板事件,供级联选择器判断是否收起面板 | Function |
级联面板 插槽
| 名称 | 说明 |
|---|---|
| default | 自定义节点内容;作用域为 node、data;作用域类型 ^[object]` |
| empty | 无数据时面板内容 |
级联面板 暴露
| 名称 | 说明 | 类型 |
|---|---|---|
| getCheckedNodes | 获取当前选中节点数组;leafOnly 为 true 时仅返回叶子选中节点,默认 false | Function |
| clearCheckedNodes | 清空已选节点 | Function |
级联选择器配置项(CascaderProps)
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| expandTrigger | 子级展开触发方式 | enum | click |
| multiple | 是否多选 | boolean | false |
| checkStrictly | 选中状态是否不关联父子 | boolean | false |
| emitPath | 选中变化时是否返回节点路径数组;为 false 时仅返回节点值 | boolean | true |
| lazy | 是否动态加载子节点,需配合 lazyLoad | boolean | false |
| lazyLoad | 动态加载子节点数据;仅 lazy 为 true 时生效;支持 reject 参数 | Function | — |
| value | 节点对象中作为取值的键名 | string | value |
| label | 节点对象中作为标签的键名 | string | label |
| children | 节点对象中作为子级的键名 | string | children |
| disabled | 节点对象中表示禁用的键名 | string | disabled |
| leaf | 节点对象中表示叶子节点的键名 | string | leaf |
| hoverThreshold | 悬停展开的阈值(毫秒) | number | 500 |
| checkOnClickNode | 点击节点时是否切换选中 | boolean | false |
| checkOnClickLeaf | 是否仅在点击叶子节点时切换选中 | boolean | true |
| showPrefix | 是否显示单选/多选前缀图标 | boolean | true |
类型声明
展开类型声明
type CascaderNodeValue = string | number
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 Record<string, 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
}
class Node {
readonly uid: number
readonly level: number
readonly value: CascaderNodeValue
readonly label: string
readonly pathNodes: Node[]
readonly pathValues: CascaderNodePathValue
readonly pathLabels: string[]
childrenData: ChildrenData
children: Node[]
text: string
loaded: boolean
/**
* 是否选中
*
* @default false
*/
checked: boolean
/**
* 表示未全选子节点与全选子节点之间的中间态
*
* @default false
*/
indeterminate: boolean
/**
* 加载状态
*
* @default false
*/
loading: boolean
// 访问器
isDisabled: boolean
isLeaf: boolean
valueByOption: CascaderNodeValue | CascaderNodePathValue
// 方法
appendChild(childData: CascaderOption): Node
calcText(allLevels: boolean, separator: string): string
broadcast(): void
emit(): void
onParentCheck(checked: boolean): void
onChildCheck(): void
setCheckState(checked: boolean): void
doCheck(checked: boolean): void
}
Node as CascaderNode