diff --git a/src/cascader/__test__/__snapshots__/demo.test.jsx.snap b/src/cascader/__test__/__snapshots__/demo.test.jsx.snap index 749c8eb36..66973064b 100644 --- a/src/cascader/__test__/__snapshots__/demo.test.jsx.snap +++ b/src/cascader/__test__/__snapshots__/demo.test.jsx.snap @@ -108,7 +108,9 @@ exports[`Cascader > Cascader baseVue demo works fine 1`] = `
+ 选择选项 +
Cascader keysVue demo works fine 1`] = `
+ 选择选项 +
Cascader lazyVue demo works fine 1`] = `
+ 选择选项 +
Cascader mobileVue demo works fine 1`] = `
+ 选择选项 +
Cascader mobileVue demo works fine 1`] = `
+ 选择选项 +
Cascader mobileVue demo works fine 1`] = `
+ 选择选项 +
Cascader mobileVue demo works fine 1`] = `
+ 选择选项 +
Cascader mobileVue demo works fine 1`] = `
+ 选择选项 +
Cascader withTitleVue demo works fine 1`] = `
+ 选择选项 +
Cascader withValueVue demo works fine 1`] = `
+ 选择选项 +
events > : pick 1`] = `
+ 选择选项 +
{ describe('props', () => { it(':visible ', async () => { @@ -214,6 +216,12 @@ describe('cascader', () => { }); }); + it(': placeholder', async () => { + const wrapper = mount(); + const $placeholder = wrapper.find(`.${name}__step-label`); + expect($placeholder.text()).toEqual(defaultPlaceholder); + }); + it(': subTitles', async () => { const wrapper = mount(); const $subTitles = wrapper.find(`.${name}__options-title`); @@ -256,6 +264,16 @@ describe('cascader', () => { expect($title.text()).toBe(title); }); + it(': placeholder', () => { + const wrapper = mount(, { + slots: { + placeholder: defaultPlaceholder, + }, + }); + const $placeholder = wrapper.find(`.${name}__step-label`); + expect($placeholder.text()).toBe(defaultPlaceholder); + }); + it(': closeBtn', () => { const closeBtn = '关闭'; const wrapper = mount(, { diff --git a/src/cascader/cascader.en-US.md b/src/cascader/cascader.en-US.md index a0cc98c9d..254408b75 100644 --- a/src/cascader/cascader.en-US.md +++ b/src/cascader/cascader.en-US.md @@ -15,6 +15,7 @@ title | String / Slot / Function | - | Typescript:`string \| TNode`。[see mor value | String / Number | - | `v-model` and `v-model:value` is supported | N defaultValue | String / Number | - | uncontrolled property | N visible | Boolean | false | \- | N +placeholder | String / Slot / Function | 选择选项 | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N onChange | Function | | Typescript:`(value: string \| number, selectedOptions: string[]) => void`
| N onClose | Function | | Typescript:`(trigger: TriggerSource) => void`
[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/cascader/type.ts)。
`type TriggerSource = 'overlay' \| 'close-btn' \| 'finish'`
| N onPick | Function | | Typescript:`(context: { level: number; value: string | number; index: number }) => void`
| N diff --git a/src/cascader/cascader.md b/src/cascader/cascader.md index d1d8ef685..a1909c90a 100644 --- a/src/cascader/cascader.md +++ b/src/cascader/cascader.md @@ -14,6 +14,7 @@ title | String / Slot / Function | - | 标题。TS 类型:`string \| TNode`。 value | String / Number | - | 选项值。支持语法糖 `v-model` 或 `v-model:value` | N defaultValue | String / Number | - | 选项值。非受控属性 | N visible | Boolean | false | 是否展示 | N +placeholder | String / Slot / Function | 选择选项 | 未选中时的提示文案。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N onChange | Function | | TS 类型:`(value: string \| number, selectedOptions: string[]) => void`
值发生变更时触发 | N onClose | Function | | TS 类型:`(trigger: TriggerSource) => void`
关闭时触发。[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/cascader/type.ts)。
`type TriggerSource = 'overlay' \| 'close-btn' \| 'finish'`
| N onPick | Function | | TS 类型:`(context: { level: number, value: string \| number, index: number }) => void`
选择后触发 | N diff --git a/src/cascader/cascader.vue b/src/cascader/cascader.vue index 77d6b3d70..dfd08b851 100644 --- a/src/cascader/cascader.vue +++ b/src/cascader/cascader.vue @@ -16,7 +16,7 @@ :class="[ `${name}__step-dot`, { - 't-cascader__step-dot--active': item !== defaultOptionLabel, + 't-cascader__step-dot--active': item !== placeholder, 't-cascader__step-dot--last': index === steps.length - 1, }, ]" @@ -29,7 +29,11 @@ }, ]" > - {{ item }} + + @@ -93,7 +97,6 @@ import { TreeOptionData } from '../common'; const { prefix } = config; const name = `${prefix}-cascader`; -const defaultOptionLabel = '选择选项'; interface ChildrenInfoType { value: string | number; @@ -128,12 +131,20 @@ export default defineComponent({ const open = ref(visible.value || false); const [cascaderValue, setCascaderValue] = useVModel(value, modelValue, props.defaultValue, props.onChange); const title = computed(() => props.title || '标题'); + const placeholder = computed(() => props.placeholder || '选择选项'); const stepIndex = ref(0); const selectedIndexes = reactive([]); const selectedValue = reactive([]); const items: Array> = reactive([options.value ?? []]); - const steps = reactive([defaultOptionLabel]); + const steps = reactive([placeholder.value]); + + watch(placeholder, (newValue, oldValue) => { + const index = steps.indexOf(oldValue); + if (index !== -1) { + steps[index] = newValue; + } + }); onMounted(() => { initWithValue(); @@ -146,6 +157,7 @@ export default defineComponent({ }); }); const titleTNode = computed(() => renderTNode(internalInstance, 'title')); + const placeholderTNode = computed(() => renderTNode(internalInstance, 'placeholder')); const initWithValue = () => { if (value.value != null) { @@ -172,7 +184,7 @@ export default defineComponent({ } } if (steps.length < items.length) { - steps.push(defaultOptionLabel); + steps.push(placeholder.value); } stepIndex.value = items.length - 1; }; @@ -212,7 +224,7 @@ export default defineComponent({ items[level + 1] = item[(keys as Ref).value?.children ?? 'children']; items.length = level + 2; stepIndex.value += 1; - steps[level + 1] = '选择选项'; + steps[level + 1] = placeholder.value; steps.length = level + 2; } else if (item[(keys as Ref).value?.children ?? 'children']?.length === 0) { childrenInfo.value = e; @@ -269,13 +281,14 @@ export default defineComponent({ return { open, - defaultOptionLabel, + placeholder, onVisibleChange, onStepClick, onTabChange, handleSelect, closeBtnTNode, titleTNode, + placeholderTNode, stepIndex, name, title, diff --git a/src/cascader/props.ts b/src/cascader/props.ts index 3b0b23ecc..67c8f6354 100644 --- a/src/cascader/props.ts +++ b/src/cascader/props.ts @@ -53,6 +53,10 @@ export default { defaultValue: { type: [String, Number] as PropType, }, + /** 未选中时的提示文案 */ + placeholder: { + type: [String, Function] as PropType, + }, /** 是否展示 */ visible: Boolean, /** 值发生变更时触发 */ diff --git a/src/cascader/type.ts b/src/cascader/type.ts index 2fe5cea23..fcdae0a07 100644 --- a/src/cascader/type.ts +++ b/src/cascader/type.ts @@ -52,6 +52,10 @@ export interface TdCascaderProps Form horizontalVue demo works fine 1`] = `
+ 选择选项 +
Form mobileVue demo works fine 1`] = `
+ 选择选项 +
Form verticalVue demo works fine 1`] = `
+ 选择选项 +