Cascader 级联选择 - Vant 4
Cascader 级联选择
🔗 介绍
想象一下,你正在网购时需要选择收货地址 📍,从省份到城市再到区县,一层层地精准定位。Cascader 级联选择组件就像一个智能的"地图导航员" 🗺️,帮你在复杂的层级数据中轻松穿梭!
无论是省市区三级联动、商品分类筛选,还是组织架构选择,Cascader 都能让原本繁琐的多层选择变得如丝般顺滑 ✨。它就像一个贴心的向导,一步步引导用户找到最终目标,让复杂的数据结构在指尖变得简单易懂!
📦 引入
通过以下方式来全局注册组件,更多注册方式请参考组件注册。
import { createApp } from'vue';
import { Cascader } from'vant';
const app = createApp();
app.use(Cascader);🎯 代码演示
基础用法
就像搭积木一样简单 🧱!Cascader 与 Field 和 Popup 组件完美配合,就像三个好朋友手拉手,共同打造出丝滑的选择体验。
点击输入框,弹出层级选择面板,一层层选择下去,最终的路径会自动拼接成完整的选择结果 🎯。这种体验就像在玩一个有趣的"寻宝游戏",每一步都充满期待!
import { ref } from'vue';
export default {
setup() {
const show = ref(false);
const fieldValue = ref('');
const cascaderValue = ref('');
// 选项列表,children 代表子选项,支持多级嵌套
const options = [ { text: '浙江省', value: '330000', children: [{ text: '杭州市', value: '330100' }], }, { text: '江苏省', value: '320000', children: [{ text: '南京市', value: '320100' }], }, ];
// 全部选项选择完毕后,会触发 finish 事件
const onFinish = ({ selectedOptions }) => {
show.value = false;
fieldValue.value = selectedOptions.map((option) => option.text).join('/');
};
return { show, options, onFinish, fieldValue, cascaderValue, };
}
};中国省市区数据
做电商应用最头疼的是什么?当然是省市区数据啦 😅!别担心,Vant 就像一个贴心的管家,已经为你准备好了一份完整的中国省市区数据 🇨🇳。
这份数据就像一个"地理百科全书",从黑龙江到海南,从新疆到上海,应有尽有!只需要安装一个小小的 npm 包,就能让你的应用瞬间拥有全国地址选择能力 🚀:
# 通过 npm
npm i @vant/area-data
# 通过 yarn
yarn add @vant/area-data
# 通过 pnpm p
npm add @vant/area-data
# 通过 Bun
bun add @vant/area-dataimport { ref } from'vue';
import { useCascaderAreaData } from'@vant/area-data';
export default { setup() {
const show = ref(false);
const fieldValue = ref('');
const cascaderValue = ref('');
const options = useCascaderAreaData();
const onFinish = ({ selectedOptions }) => { show.value = false; fieldValue.value = selectedOptions.map((option) => option.text).join('/'); };
return { show, options, onFinish, fieldValue, cascaderValue, };
},
};Tips: 中国的行政区划每年都会有变动,如果发现省市区数据未及时更新,欢迎提 Pull Request 帮助我们更新。你可以在「国家统计局 - 全国区划代码」 和「民政部 - 行政区划代码」上查询到最新数据,请根据官方数据进行核实。
自定义颜色
想要让你的级联选择器更有个性?🎨 active-color 属性就像一支神奇的画笔,可以为选中状态涂上你喜欢的颜色!
无论是品牌蓝、活力橙还是优雅紫,都能让你的组件与众不同,完美融入应用的整体设计风格 ✨。
异步加载选项
有时候数据太多,一次性加载会让用户等得花儿都谢了 🌸。这时候异步加载就像一个"智能快递员" 📦,按需配送,用户选到哪一层,就加载哪一层的数据。
通过监听 change 事件,你可以在用户选择时动态获取下级数据,让选择过程既流畅又高效!
import { ref } from'vue';
import { closeToast, showLoadingToast } from'vant';
export default { setup() {
const show = ref(false);
const fieldValue = ref('');
const cascaderValue = ref('');
const options = ref([ { text: '浙江省', value: '330000', children: [], }, ]);
const onChange = ({ value }) => {
if ( value === options.value[0].value && options.value[0].children.length === 0 ) {
// 模拟数据请求
showLoadingToast('加载中...');
setTimeout(() => {
options.value[0].children = [ { text: '杭州市', value: '330100' }, { text: '宁波市', value: '330200' }, ];
closeToast(); }, 1000);
}
};
const onFinish = ({ selectedOptions }) => { show.value = false; fieldValue.value = selectedOptions.map((option) => option.text).join('/'); };
return { show, options, onFinish, fieldValue, cascaderValue, };
},
};自定义字段名
每个项目都有自己的"语言习惯" 🗣️,有的喜欢用 name,有的偏爱 title,有的钟情于 label。Cascader 就像一个"翻译官" 🌐,通过 field-names 属性让你的数据结构和组件完美对接!
不管你的后端同事用什么字段名,Cascader 都能轻松适配,让数据对接变得毫无压力 💪。
import { ref } from'vue'; exportdefault { setup() { const code = ref(''); const fieldNames = { text: 'name', value: 'code', children: 'items', }; const options = [ { name: '浙江省', code: '330000', items: [{ name: '杭州市', code: '330100' }], }, { name: '江苏省', code: '320000', items: [{ name: '南京市', code: '320100' }], }, ]; return { code, options, fieldNames, }; }, };自定义选项上方内容
想要在选项列表上方加点"调料" 🧂?比如一个搜索框、一段提示文字,或者一个可爱的小图标?
通过插槽的魔法,你可以在每一层选项的上方添加任何你想要的内容,让选择体验更加丰富多彩 🌈!
import { ref } from'vue'; exportdefault { setup() { const code = ref(''); const options = [ { name: '浙江省', code: '330000', items: [{ name: '杭州市', code: '330100' }], }, { name: '江苏省', code: '320000', items: [{ name: '南京市', code: '320100' }], }, ]; return { code, options, }; }, };API
Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| v-model | 选中项的值 | *string | number* |
| title | 顶部标题 | string | - |
| options | 可选项数据源 | CascaderOption[] | [] |
| placeholder | 未选中时的提示文案 | string | 请选择 |
| active-color | 选中状态的高亮颜色 | string | #1989fa |
| swipeable | 是否开启手势左右滑动切换 | boolean | true | | closeable | 是否显示关闭图标 | boolean | true | | show-header | 是否展示标题栏 | boolean | true | | close-icon | 关闭图标名称或图片链接,等同于 Icon 组件的 name 属性 | string | cross |
| field-names | 自定义 options 结构中的字段 | CascaderFieldNames | { text: 'text', value: 'value', children: 'children' } |
CascaderOption 数据结构
options 属性是一个由对象构成的数组,数组中的每个对象配置一个可选项,对象可以包含以下值:
| 键名 | 说明 | 类型 |
|---|---|---|
| text | 选项文字(必填) | string |
| value | 选项对应的值(必填) | *string |
| color | 选项文字颜色 | string |
| children | 子选项列表 | CascaderOption[] |
| disabled | 是否禁用选项 | boolean |
| className | 为对应列添加额外的 class | *string |
Events
| 事件 | 说明 | 回调参数 |
|---|---|---|
| change | 选中项变化时触发 | *{ value: string |
| finish | 全部选项选择完成后触发 | *{ value: string |
| close | 点击关闭图标时触发 | - |
| click-tab | 点击标签时触发 | tabIndex: number, title: string |
Slots
| 名称 | 说明 | 参数 |
|---|---|---|
| title | 自定义顶部标题 | - |
| option | 自定义选项文字 | { option: CascaderOption, selected: boolean } |
| options-top | 自定义选项上方的内容 | { tabIndex: number } |
| options-bottom | 自定义选项下方的内容 | { tabIndex: number } |
类型定义
组件导出以下类型定义:
importtype { CascaderProps, CascaderOption, CascaderFieldNames } from'vant';主题定制
样式变量
组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 ConfigProvider 组件。
| 名称 | 默认值 | 描述 |
|---|---|---|
| --van-cascader-header-height | 48px | - |
| --van-cascader-header-padding | 0 var(--van-padding-md) | - |
| --van-cascader-title-font-size | var(--van-font-size-lg) | - |
| --van-cascader-title-line-height | 20px | - |
| --van-cascader-close-icon-size | 22px | - |
| --van-cascader-close-icon-color | var(--van-gray-5) | - |
| --van-cascader-selected-icon-size | 18px | - |
| --van-cascader-tabs-height | 48px | - |
| --van-cascader-active-color | var(--van-danger-color) | - |
| --van-cascader-options-height | 384px | - |
| --van-cascader-option-disabled-color | var(--van-text-color-3) | - |
| --van-cascader-tab-color | var(--van-text-color) | - |
| --van-cascader-unselected-tab-color | var(--van-text-color-2) | - |
🎯 最佳实践
💡 使用场景推荐
Cascader 就像一个万能的"分类大师",在各种场景下都能发挥重要作用:
🏠 地址选择
<!-- 经典的省市区三级联动 -->
<van-cascader
v-model="addressCode"
title="选择地址"
:options="areaOptions"
@finish="onAddressFinish"
/>🏢 组织架构选择
<!-- 公司部门层级选择 -->
<van-cascader
v-model="departmentId"
title="选择部门"
:options="departmentOptions"
placeholder="请选择所属部门"
/>📱 商品分类筛选
<!-- 电商商品分类选择 -->
<van-cascader
v-model="categoryId"
title="商品分类"
:options="categoryOptions"
active-color="#ff6034"
/>📚 知识分类导航
<!-- 文档或知识库分类 -->
<van-cascader
v-model="topicId"
title="选择主题"
:options="topicOptions"
:field-names="{ text: 'title', value: 'id', children: 'subTopics' }"
/>⚡ 性能优化小贴士
- 数据懒加载:对于大量数据,使用异步加载避免首次渲染卡顿
- 合理的层级深度:建议控制在 3-4 层,过深会影响用户体验
- 数据缓存:对于相对固定的数据(如地区信息),可以进行本地缓存
- 虚拟滚动:当单层选项过多时,考虑使用虚拟滚动优化性能
🎨 设计建议
- 层级指示:清晰的标签页设计让用户知道当前选择的层级
- 选中状态:明显的选中状态反馈,让用户清楚自己的选择
- 加载状态:异步加载时提供友好的加载提示
- 错误处理:网络异常时提供重试机制和错误提示
🔧 常见问题解决
Q: 如何实现搜索功能? A: 可以通过 options-top 插槽添加搜索框,结合数据过滤实现搜索。
Q: 如何设置默认选中值? A: 设置 v-model 的初始值为目标选项的 value 即可。
Q: 异步加载失败怎么办? A: 在 change 事件中添加错误处理,提供重试按钮或错误提示。
Q: 如何限制选择层级? A: 可以在数据结构中控制 children 的层级深度,或在 change 事件中进行判断。
🎪 高级用法示例
动态禁用选项
// 根据业务逻辑动态禁用某些选项
const processOptions = (options, parentValue) => {
return options.map(option => ({
...option,
disabled: shouldDisableOption(option, parentValue),
children: option.children ? processOptions(option.children, option.value) : []
}));
};自定义选项渲染
<van-cascader v-model="value" :options="options">
<template #option="{ option, selected }">
<div class="custom-option">
<span>{{ option.text }}</span>
<van-icon v-if="option.hot" name="fire" color="red" />
<van-tag v-if="selected" size="mini" type="primary">已选</van-tag>
</div>
</template>
</van-cascader>🔗 相关组件
- Picker 选择器 - 单列或多列选择器
- DatePicker 日期选择 - 专门的日期时间选择
- Area 省市区选择 - 专门的地区选择组件
- TreeSelect 分类选择 - 树形结构的分类选择
- Field 输入框 - 常与 Cascader 配合使用
- Popup 弹出层 - Cascader 的容器组件
📚 延伸阅读
💡 小提示:好的级联选择器就像一个优秀的导游,不仅要知道路怎么走,还要让游客在选择的过程中感到轻松愉快。合理运用 Cascader 的各种特性,可以让复杂的数据选择变得简单而有趣!