404 lines
10 KiB
Markdown
404 lines
10 KiB
Markdown
|
|
# Cascader 级联选择
|
|||
|
|
|
|||
|
|
### 介绍
|
|||
|
|
|
|||
|
|
级联选择框,用于多层级数据的选择,典型场景为省市区选择。
|
|||
|
|
|
|||
|
|
### 引入
|
|||
|
|
|
|||
|
|
通过以下方式来全局注册组件,更多注册方式请参考[组件注册](#/zh-CN/advanced-usage#zu-jian-zhu-ce)。
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import { createApp } from 'vue';
|
|||
|
|
import { Cascader } from 'vant';
|
|||
|
|
|
|||
|
|
const app = createApp();
|
|||
|
|
app.use(Cascader);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 代码演示
|
|||
|
|
|
|||
|
|
### 基础用法
|
|||
|
|
|
|||
|
|
级联选择组件可以搭配 Field 和 Popup 组件使用,示例如下:
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<van-field
|
|||
|
|
v-model="fieldValue"
|
|||
|
|
is-link
|
|||
|
|
readonly
|
|||
|
|
label="地区"
|
|||
|
|
placeholder="请选择所在地区"
|
|||
|
|
@click="show = true"
|
|||
|
|
/>
|
|||
|
|
<van-popup v-model:show="show" round position="bottom">
|
|||
|
|
<van-cascader
|
|||
|
|
v-model="cascaderValue"
|
|||
|
|
title="请选择所在地区"
|
|||
|
|
:options="options"
|
|||
|
|
@close="show = false"
|
|||
|
|
@finish="onFinish"
|
|||
|
|
/>
|
|||
|
|
</van-popup>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
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,
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 中国省市区数据
|
|||
|
|
|
|||
|
|
Cascader 组件常用于选择省市区,Vant 提供了一份中国省市区数据,你可以安装 [@vant/area-data](https://github.com/vant-ui/vant/tree/main/packages/vant-area-data) npm 包来引入:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 通过 npm
|
|||
|
|
npm i @vant/area-data
|
|||
|
|
|
|||
|
|
# 通过 yarn
|
|||
|
|
yarn add @vant/area-data
|
|||
|
|
|
|||
|
|
# 通过 pnpm
|
|||
|
|
pnpm add @vant/area-data
|
|||
|
|
|
|||
|
|
# 通过 Bun
|
|||
|
|
bun add @vant/area-data
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<van-field
|
|||
|
|
v-model="fieldValue"
|
|||
|
|
is-link
|
|||
|
|
readonly
|
|||
|
|
label="地区"
|
|||
|
|
placeholder="请选择所在地区"
|
|||
|
|
@click="show = true"
|
|||
|
|
/>
|
|||
|
|
<van-popup v-model:show="show" round position="bottom">
|
|||
|
|
<van-cascader
|
|||
|
|
v-model="cascaderValue"
|
|||
|
|
title="请选择所在地区"
|
|||
|
|
:options="options"
|
|||
|
|
@close="show = false"
|
|||
|
|
@finish="onFinish"
|
|||
|
|
/>
|
|||
|
|
</van-popup>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import { 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 帮助我们更新。你可以在[「国家统计局 - 全国区划代码」](http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/) 和[「民政部 - 行政区划代码」](https://www.mca.gov.cn/article/sj/xzqh/1980/)上查询到最新数据,请根据官方数据进行核实。
|
|||
|
|
|
|||
|
|
### 自定义颜色
|
|||
|
|
|
|||
|
|
通过 `active-color` 属性来设置选中状态的高亮颜色。
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<van-cascader
|
|||
|
|
v-model="cascaderValue"
|
|||
|
|
title="请选择所在地区"
|
|||
|
|
:options="options"
|
|||
|
|
active-color="#ee0a24"
|
|||
|
|
@close="show = false"
|
|||
|
|
@finish="onFinish"
|
|||
|
|
/>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 异步加载选项
|
|||
|
|
|
|||
|
|
可以监听 `change` 事件并动态设置 `options`,实现异步加载选项。
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<van-field
|
|||
|
|
v-model="fieldValue"
|
|||
|
|
is-link
|
|||
|
|
readonly
|
|||
|
|
label="地区"
|
|||
|
|
placeholder="请选择所在地区"
|
|||
|
|
@click="show = true"
|
|||
|
|
/>
|
|||
|
|
<van-popup v-model:show="show" round position="bottom">
|
|||
|
|
<van-cascader
|
|||
|
|
v-model="cascaderValue"
|
|||
|
|
title="请选择所在地区"
|
|||
|
|
:options="options"
|
|||
|
|
@close="show = false"
|
|||
|
|
@change="onChange"
|
|||
|
|
@finish="onFinish"
|
|||
|
|
/>
|
|||
|
|
</van-popup>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
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,
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 自定义字段名
|
|||
|
|
|
|||
|
|
通过 `field-names` 属性可以自定义 `options` 里的字段名称。
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<van-cascader
|
|||
|
|
v-model="code"
|
|||
|
|
title="请选择所在地区"
|
|||
|
|
:options="options"
|
|||
|
|
:field-names="fieldNames"
|
|||
|
|
/>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import { ref } from 'vue';
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
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,
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 自定义选项上方内容
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<van-cascader v-model="code" title="请选择所在地区" :options="options">
|
|||
|
|
<template #options-top="{ tabIndex }">
|
|||
|
|
<div class="current-level">当前为第 {{ tabIndex + 1 }} 级</div>
|
|||
|
|
</template>
|
|||
|
|
</van-cascader>
|
|||
|
|
|
|||
|
|
<style>
|
|||
|
|
.current-level {
|
|||
|
|
font-size: 14px;
|
|||
|
|
padding: 16px 16px 0;
|
|||
|
|
color: var(--van-gray-6);
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import { ref } from 'vue';
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
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 属性](#/zh-CN/icon#props) | _string_ | `cross` |
|
|||
|
|
| field-names | 自定义 `options` 结构中的字段 | _CascaderFieldNames_ | `{ text: 'text', value: 'value', children: 'children' }` |
|
|||
|
|
|
|||
|
|
### CascaderOption 数据结构
|
|||
|
|
|
|||
|
|
`options` 属性是一个由对象构成的数组,数组中的每个对象配置一个可选项,对象可以包含以下值:
|
|||
|
|
|
|||
|
|
| 键名 | 说明 | 类型 |
|
|||
|
|
| --------- | ------------------------ | --------------------------- |
|
|||
|
|
| text | 选项文字(必填) | _string_ |
|
|||
|
|
| value | 选项对应的值(必填) | _string \| number_ |
|
|||
|
|
| color | 选项文字颜色 | _string_ |
|
|||
|
|
| children | 子选项列表 | _CascaderOption[]_ |
|
|||
|
|
| disabled | 是否禁用选项 | _boolean_ |
|
|||
|
|
| className | 为对应列添加额外的 class | _string \| Array \| object_ |
|
|||
|
|
|
|||
|
|
### Events
|
|||
|
|
|
|||
|
|
| 事件 | 说明 | 回调参数 |
|
|||
|
|
| --- | --- | --- |
|
|||
|
|
| change | 选中项变化时触发 | _{ value: string \| number, selectedOptions: CascaderOption[], tabIndex: number }_ |
|
|||
|
|
| finish | 全部选项选择完成后触发 | _{ value: string \| number, selectedOptions: CascaderOption[], tabIndex: number }_ |
|
|||
|
|
| close | 点击关闭图标时触发 | - |
|
|||
|
|
| click-tab | 点击标签时触发 | _tabIndex: number, title: string_ |
|
|||
|
|
|
|||
|
|
### Slots
|
|||
|
|
|
|||
|
|
| 名称 | 说明 | 参数 |
|
|||
|
|
| --- | --- | --- |
|
|||
|
|
| title | 自定义顶部标题 | - |
|
|||
|
|
| option | 自定义选项文字 | _{ option: CascaderOption, selected: boolean }_ |
|
|||
|
|
| options-top | 自定义选项上方的内容 | _{ tabIndex: number }_ |
|
|||
|
|
| options-bottom | 自定义选项下方的内容 | _{ tabIndex: number }_ |
|
|||
|
|
|
|||
|
|
### 类型定义
|
|||
|
|
|
|||
|
|
组件导出以下类型定义:
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
import type { CascaderProps, CascaderOption, CascaderFieldNames } from 'vant';
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 主题定制
|
|||
|
|
|
|||
|
|
### 样式变量
|
|||
|
|
|
|||
|
|
组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 [ConfigProvider 组件](#/zh-CN/config-provider)。
|
|||
|
|
|
|||
|
|
| 名称 | 默认值 | 描述 |
|
|||
|
|
| ------------------------------------ | ------------------------- | ---- |
|
|||
|
|
| --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)_ | - |
|