From 2f767df423f023a663250e3b5296b6b4e01f7672 Mon Sep 17 00:00:00 2001 From: 07akioni <07akioni2@gmail.com> Date: Wed, 9 Dec 2020 00:11:06 +0800 Subject: [PATCH] feat(select): default-value --- .../select/enUS/index.demo-entry.md | 3 +- .../select/zhCN/index.demo-entry.md | 3 +- src/select/src/Select.vue | 36 ++++++++++++------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/demo/documentation/components/select/enUS/index.demo-entry.md b/demo/documentation/components/select/enUS/index.demo-entry.md index 7a3c5a053..7cb76d1d3 100644 --- a/demo/documentation/components/select/enUS/index.demo-entry.md +++ b/demo/documentation/components/select/enUS/index.demo-entry.md @@ -24,6 +24,7 @@ fallback-option |Name|Type|Default|Description| |-|-|-|-| |clearable|`boolean`|`false`|| +|default-value|`Array \| string \| number \| null`|`null`|| |disabled|`boolean`|`false`|| |fallback-option|`false \| (value: string \| number) => SelectOption`|`value => ({ label: '' + value, value })`|The option to be created according the value which has no corresponding option in the options of the component. If set to `false`, the fallback option won't be created and displayed and the value has no corresponding option will be viewed as a invalid value and it will be removed in the operations of the component.| |filterable|`boolean`|`false`|Whether it can filter options.| @@ -36,7 +37,7 @@ fallback-option |size|`'small' \| 'medium' \| 'large'`|`'medium'`|| |tag|`boolean`|`false`|Whether it can create new option, should be used with `filterable`.| |theme|`'light' \| 'dark' \| string`|`undefined`|| -|value|`Array \| string \| number`|`false`|| +|value|`Array \| string \| number \| null`|`undefined`|| |on-blur|`() => any`|Selection blur.| |on-create|`(label: string) => SelectOption`|`label => ({ label, value: label })`|How to create a option when you input a string to create a option. Note that `filter` will be applied to the created option too. And make sure the value of the created option is not the same as any other option.| |on-focus|`() => any`|Selection focus.| diff --git a/demo/documentation/components/select/zhCN/index.demo-entry.md b/demo/documentation/components/select/zhCN/index.demo-entry.md index b67b95459..9a8ce16e0 100644 --- a/demo/documentation/components/select/zhCN/index.demo-entry.md +++ b/demo/documentation/components/select/zhCN/index.demo-entry.md @@ -26,6 +26,7 @@ menu-debug |名称|类型|默认值|说明| |-|-|-|-| |clearable|`boolean`|`false`|| +|default-value|`Array \| string \| number \| null`|`null`|| |disabled|`boolean`|`false`|| |fallback-option|`false \| (value: string \| number) => SelectOption`|`value => ({ label: '' + value, value })`|在传入的选项中没有对应当前值的选项时,这个值应该对应的选项。如果设为 `false`,不会为找不到对应选项的值生成回退选项也不会显示它,未在选项中的值会被视为不合法,操作过程中会被组件清除掉| |filterable|`boolean`|`false`|是否可以过滤| @@ -38,7 +39,7 @@ menu-debug |size|`'small' \| 'medium' \| 'large'`|`'medium'`|| |tag|`boolean`|`false`|是否可以创建新的选项,需要和 `filterable` 一起使用| |theme|`'light' \| 'dark' \| string`|`undefined`|| -|value|`Array \| string \| number`|`false`|| +|value|`Array \| string \| number \| null`|`undefined`|| |on-blur|`() => any`|选择器 Blur 时发出| |on-create|`(label: string) => SelectOption`|`label => ({ label, value: label })`|在输入内容时如何创建一个选项。注意 `filter` 对这个生成的选项同样会生效。同时确保这个选项和其他选项的 `value` 不要有重复| |on-focus|`() => any`|选择器 Focus 时发出| diff --git a/src/select/src/Select.vue b/src/select/src/Select.vue index 2d5963306..1416b3450 100644 --- a/src/select/src/Select.vue +++ b/src/select/src/Select.vue @@ -66,7 +66,7 @@ :multiple="multiple" size="medium" :filterable="filterable" - :value="value" + :value="mergedValue" @menu-toggle-option="handleToggleOption" @scroll="handleMenuScroll" > @@ -195,10 +195,14 @@ export default { type: Array, required: true }, - value: { + defaultValue: { type: [String, Number, Array], default: null }, + value: { + type: [String, Number, Array], + default: undefined + }, placeholder: { type: String, default: undefined @@ -313,6 +317,9 @@ export default { } }, setup (props) { + const uncontrolledValueRef = ref(props.defaultValue) + const controlledValueRef = toRef(props, 'value') + const mergedValueRef = useMergedState(controlledValueRef, uncontrolledValueRef) const patternRef = ref('') const filteredOptionsRef = computed(() => filterOptions( props.options, @@ -354,6 +361,8 @@ export default { createdOptions: ref([]), beingCreatedOptions: ref([]), memoValOptMap: ref(new Map()), + uncontrolledValue: uncontrolledValueRef, + mergedValue: mergedValueRef, followerRef } }, @@ -382,7 +391,7 @@ export default { }, selectedOptions () { if (this.multiple) { - const { value: values } = this + const { mergedValue: values } = this if (!Array.isArray(values)) return [] const remote = this.remote const { @@ -409,17 +418,17 @@ export default { }, selectedOption () { if (!this.multiple) { - const { value, valOptMap, wrappedFallbackOption } = this - if (value === null) return null + const { mergedValue, valOptMap, wrappedFallbackOption } = this + if (mergedValue === null) return null let selectedOption = null - if (valOptMap.has(value)) { - selectedOption = valOptMap.get(value) + if (valOptMap.has(mergedValue)) { + selectedOption = valOptMap.get(mergedValue) } else if (this.remote) { - selectedOption = this.memoValOptMap.get(value) + selectedOption = this.memoValOptMap.get(mergedValue) } return ( selectedOption || - (wrappedFallbackOption && wrappedFallbackOption(value)) || + (wrappedFallbackOption && wrappedFallbackOption(mergedValue)) || null ) } @@ -443,7 +452,7 @@ export default { if (!this.mergedShow) return this.$nextTick(this.syncPosition) }, - value () { + mergedValue () { if (!this.mergedShow) return this.$nextTick(this.syncPosition) } @@ -461,6 +470,7 @@ export default { } = this if (onChange) call(onChange, value) if (onUpdateValue) call(onUpdateValue, value) + this.uncontrolledValue = value nTriggerFormChange() nTriggerFormInput() }, @@ -586,7 +596,7 @@ export default { this.memoValOptMap.set(option.value, option) } if (this.multiple) { - const changedValue = this.createClearedMultipleSelectValue(this.value) + const changedValue = this.createClearedMultipleSelectValue(this.mergedValue) const index = changedValue.findIndex(value => value === option.value) if (~index) { changedValue.splice(index, 1) @@ -620,7 +630,7 @@ export default { }, handleDeleteLastOption (e) { if (!this.pattern.length) { - const changedValue = this.createClearedMultipleSelectValue(this.value) + const changedValue = this.createClearedMultipleSelectValue(this.mergedValue) if (Array.isArray(changedValue)) { const poppedValue = changedValue.pop() const createdOptionIndex = this.getCreatedOptionIndex(poppedValue) @@ -636,7 +646,7 @@ export default { ) }, handlePatternInput (e) { - const value = e.target.value + const { value } = e.target this.pattern = value const { onSearch, tag, remote } = this if (onSearch) {