From 70e16f0b0b988a7a53a41c7f1b4f35721d518857 Mon Sep 17 00:00:00 2001 From: weiqifu <330729121@qq.com> Date: Mon, 23 Oct 2023 17:50:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(cascader):=20=E6=96=B0=E5=A2=9E=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E9=80=89=E9=A1=B9=E6=A0=87=E7=AD=BE=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E8=87=AA=E5=AE=9A=E4=B9=89=E5=AE=9A=E5=88=B6=E7=BA=A7?= =?UTF-8?q?=E8=81=94=E7=BB=84=E4=BB=B6=E4=B8=AD=E2=80=9C=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E9=80=89=E9=A1=B9=E2=80=9D=E6=96=87=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: #1130 --- .../__test__/__snapshots__/demo.test.jsx.snap | 20 +++++++++++++ .../__snapshots__/index.test.jsx.snap | 2 ++ src/cascader/__test__/index.test.jsx | 20 +++++++++---- src/cascader/cascader.en-US.md | 2 +- src/cascader/cascader.md | 2 +- src/cascader/cascader.vue | 30 ++++++++++++++----- src/cascader/props.ts | 6 ++-- src/cascader/type.ts | 4 +-- .../__test__/__snapshots__/demo.test.jsx.snap | 6 ++++ 9 files changed, 73 insertions(+), 19 deletions(-) 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', () => { @@ -216,10 +216,10 @@ describe('cascader', () => { }); }); - it(': defaultOptionLabel', async () => { - const wrapper = mount(); - const $defaultOptionLabel = wrapper.find(`.${name}__step-label`); - expect($defaultOptionLabel.text()).toEqual(defaultOptionLabel); + it(': placeholder', async () => { + const wrapper = mount(); + const $placeholder = wrapper.find(`.${name}__step-label`); + expect($placeholder.text()).toEqual(defaultPlaceholder); }); it(': subTitles', async () => { @@ -264,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 b9dff5cd2..254408b75 100644 --- a/src/cascader/cascader.en-US.md +++ b/src/cascader/cascader.en-US.md @@ -15,7 +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 -defaultOptionLabel | String | 选择选项 | \- | 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 d0aeb5ee8..a1909c90a 100644 --- a/src/cascader/cascader.md +++ b/src/cascader/cascader.md @@ -14,7 +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 -defaultOptionLabel | String | 选择选项 | 默认选项标签 | 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 156c5f2a6..cea8f6d7a 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 }} + + @@ -127,13 +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 defaultOptionLabel = props.defaultOptionLabel || '选择选项'; + 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,8 @@ export default defineComponent({ } } if (steps.length < items.length) { - steps.push(defaultOptionLabel); + console.log('placeholder.value', placeholder.value); + steps.push(placeholder.value); } stepIndex.value = items.length - 1; }; @@ -210,9 +223,11 @@ export default defineComponent({ if (item[(keys as Ref).value?.children ?? 'children']?.length) { items[level + 1] = item[(keys as Ref).value?.children ?? 'children']; + console.log('placeholder.value', placeholder.value); + 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 +284,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 0e72c9fa4..67c8f6354 100644 --- a/src/cascader/props.ts +++ b/src/cascader/props.ts @@ -53,9 +53,9 @@ export default { defaultValue: { type: [String, Number] as PropType, }, - /** 默认选项标签 */ - defaultOptionLabel: { - type: String as PropType, + /** 未选中时的提示文案 */ + placeholder: { + type: [String, Function] as PropType, }, /** 是否展示 */ visible: Boolean, diff --git a/src/cascader/type.ts b/src/cascader/type.ts index ea15de75d..fcdae0a07 100644 --- a/src/cascader/type.ts +++ b/src/cascader/type.ts @@ -53,9 +53,9 @@ export interface TdCascaderProps Form horizontalVue demo works fine 1`] = `
+ 选择选项 +
Form mobileVue demo works fine 1`] = `
+ 选择选项 +
Form verticalVue demo works fine 1`] = `
+ 选择选项 +