mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-05 19:41:42 +08:00
feat(Cascader): add options-top slot (#9732)
* feat(Cascader): add option-top slot * refactor: use watch to listen for activeTab * test(Cascader): Add the options-top slot test * docs(Cascader): update the document 完成新功能https://github.com/youzan/vant/issues/9716 * chore(Cascader): api modification
This commit is contained in:
parent
33d777d6b2
commit
94539d8f74
@ -258,6 +258,9 @@ export default defineComponent({
|
||||
unselected: !selected,
|
||||
})}
|
||||
>
|
||||
{slots['options-top']
|
||||
? slots['options-top']({ activeTab: activeTab.value })
|
||||
: null}
|
||||
{renderOptions(options, selected, tabIndex)}
|
||||
</Tab>
|
||||
);
|
||||
@ -278,7 +281,6 @@ export default defineComponent({
|
||||
);
|
||||
|
||||
updateTabs();
|
||||
|
||||
watch(() => props.options, updateTabs, { deep: true });
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
|
@ -197,6 +197,54 @@ export default {
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Content
|
||||
|
||||
```html
|
||||
<van-cascader
|
||||
v-model="code"
|
||||
title="Select Area"
|
||||
:options="options"
|
||||
:field-names="fieldNames"
|
||||
>
|
||||
<template #options-top="{ activeTab }">
|
||||
<span>Current level {{activeTab}}</span>
|
||||
</template>
|
||||
</van-cascader>
|
||||
```
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const code = ref('');
|
||||
const fieldNames = {
|
||||
text: 'name',
|
||||
value: 'code',
|
||||
children: 'items',
|
||||
};
|
||||
const options = [
|
||||
{
|
||||
name: 'Zhejiang',
|
||||
code: '330000',
|
||||
items: [{ name: 'Hangzhou', code: '330100' }],
|
||||
},
|
||||
{
|
||||
name: 'Jiangsu',
|
||||
code: '320000',
|
||||
items: [{ name: 'Nanjing', code: '320100' }],
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
code,
|
||||
options,
|
||||
fieldNames,
|
||||
};
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
@ -239,6 +287,7 @@ export default {
|
||||
| --- | --- | --- |
|
||||
| title | Custom title | - |
|
||||
| option `v3.1.4` | Custom option text | _{ option: Option, selected: boolean }_ |
|
||||
| options-top | Custom the content above options | - |
|
||||
|
||||
### Types
|
||||
|
||||
|
@ -207,6 +207,54 @@ export default {
|
||||
};
|
||||
```
|
||||
|
||||
### 自定义选项上方内容
|
||||
|
||||
```html
|
||||
<van-cascader
|
||||
v-model="code"
|
||||
title="请选择所在地区"
|
||||
:options="options"
|
||||
:field-names="fieldNames"
|
||||
>
|
||||
<template #options-top="{ activeTab }">
|
||||
<span>当前为第{{ tabIndex }}级</span>
|
||||
</template>
|
||||
</van-cascader>
|
||||
```
|
||||
|
||||
```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,
|
||||
};
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
@ -247,10 +295,11 @@ export default {
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 | 参数 |
|
||||
| --------------- | -------------- | --------------------------------------- |
|
||||
| title | 自定义顶部标题 | - |
|
||||
| 名称 | 说明 | 参数 |
|
||||
| --- | --- | --- |
|
||||
| title | 自定义顶部标题 | - |
|
||||
| option `v3.1.4` | 自定义选项文字 | _{ option: Option, selected: boolean }_ |
|
||||
| options-top | 自定义选项上方的内容 | - |
|
||||
|
||||
### 类型定义
|
||||
|
||||
|
@ -27,6 +27,7 @@ const t = useTranslate({
|
||||
{ text: '宁波市', value: '330200' },
|
||||
],
|
||||
customFieldNames: '自定义字段名',
|
||||
customContent: '自定义内容',
|
||||
},
|
||||
'en-US': {
|
||||
area: 'Area',
|
||||
@ -46,6 +47,7 @@ const t = useTranslate({
|
||||
{ text: 'Ningbo', value: '330200' },
|
||||
],
|
||||
customFieldNames: 'Custom Field Names',
|
||||
customContent: 'Custom Content',
|
||||
},
|
||||
});
|
||||
|
||||
@ -54,6 +56,7 @@ type StateItem = {
|
||||
value: string | number | null;
|
||||
result: string;
|
||||
options?: CascaderOption[];
|
||||
tabIndex?: number;
|
||||
};
|
||||
|
||||
const baseState = reactive<StateItem>({
|
||||
@ -84,6 +87,12 @@ const fieldNames = {
|
||||
children: 'items',
|
||||
};
|
||||
|
||||
const customContentState = reactive<StateItem>({
|
||||
show: false,
|
||||
value: null,
|
||||
result: '',
|
||||
});
|
||||
|
||||
const customFieldOptions = computed(() => {
|
||||
const options = deepClone(t('options'));
|
||||
const adjustFieldName = (item: CascaderOption) => {
|
||||
@ -234,4 +243,35 @@ const onFinish = (
|
||||
/>
|
||||
</van-popup>
|
||||
</demo-block>
|
||||
|
||||
<demo-block card :title="t('customContent')">
|
||||
<van-field
|
||||
v-model="customContentState.result"
|
||||
is-link
|
||||
readonly
|
||||
:label="t('area')"
|
||||
:placeholder="t('selectArea')"
|
||||
@click="customContentState.show = true"
|
||||
/>
|
||||
<van-popup
|
||||
v-model:show="customContentState.show"
|
||||
round
|
||||
teleport="body"
|
||||
position="bottom"
|
||||
safe-area-inset-bottom
|
||||
>
|
||||
<van-cascader
|
||||
v-model="customContentState.value"
|
||||
:title="t('selectArea')"
|
||||
:options="customFieldOptions"
|
||||
:field-names="fieldNames"
|
||||
@close="customContentState.show = false"
|
||||
@finish="onFinish(customContentState, $event)"
|
||||
>
|
||||
<template #options-top="{ activeTab }">
|
||||
<span>当前为第{{ activeTab }}级</span>
|
||||
</template>
|
||||
</van-cascader>
|
||||
</van-popup>
|
||||
</demo-block>
|
||||
</template>
|
||||
|
@ -241,3 +241,23 @@ test('should allow to custom the color of option', async () => {
|
||||
const option = wrapper.find('.van-cascader__option');
|
||||
expect(option.style.color).toEqual('red');
|
||||
});
|
||||
|
||||
test(' should allow more custom content', async () => {
|
||||
const wrapper = mount(Cascader, {
|
||||
slots: {
|
||||
'options-top': ({ activeTab }) => activeTab,
|
||||
},
|
||||
props: {
|
||||
options,
|
||||
},
|
||||
});
|
||||
await later();
|
||||
wrapper
|
||||
.findAll('.van-cascader__options')[0]
|
||||
.find('.van-cascader__option')
|
||||
.trigger('click');
|
||||
wrapper.vm.$nextTick(() => {
|
||||
const top = wrapper.find('.van-tab__pane');
|
||||
expect(top.text()).toBe('1');
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user