feat(select): default-value

This commit is contained in:
07akioni 2020-12-09 00:11:06 +08:00
parent af8cccffa8
commit 2f767df423
3 changed files with 27 additions and 15 deletions

View File

@ -24,6 +24,7 @@ fallback-option
|Name|Type|Default|Description| |Name|Type|Default|Description|
|-|-|-|-| |-|-|-|-|
|clearable|`boolean`|`false`|| |clearable|`boolean`|`false`||
|default-value|`Array<string \| number> \| string \| number \| null`|`null`||
|disabled|`boolean`|`false`|| |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.| |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.| |filterable|`boolean`|`false`|Whether it can filter options.|
@ -36,7 +37,7 @@ fallback-option
|size|`'small' \| 'medium' \| 'large'`|`'medium'`|| |size|`'small' \| 'medium' \| 'large'`|`'medium'`||
|tag|`boolean`|`false`|Whether it can create new option, should be used with `filterable`.| |tag|`boolean`|`false`|Whether it can create new option, should be used with `filterable`.|
|theme|`'light' \| 'dark' \| string`|`undefined`|| |theme|`'light' \| 'dark' \| string`|`undefined`||
|value|`Array<string \| number> \| string \| number`|`false`|| |value|`Array<string \| number> \| string \| number \| null`|`undefined`||
|on-blur|`() => any`|Selection blur.| |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-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.| |on-focus|`() => any`|Selection focus.|

View File

@ -26,6 +26,7 @@ menu-debug
|名称|类型|默认值|说明| |名称|类型|默认值|说明|
|-|-|-|-| |-|-|-|-|
|clearable|`boolean`|`false`|| |clearable|`boolean`|`false`||
|default-value|`Array<string \| number> \| string \| number \| null`|`null`||
|disabled|`boolean`|`false`|| |disabled|`boolean`|`false`||
|fallback-option|`false \| (value: string \| number) => SelectOption`|`value => ({ label: '' + value, value })`|在传入的选项中没有对应当前值的选项时,这个值应该对应的选项。如果设为 `false`,不会为找不到对应选项的值生成回退选项也不会显示它,未在选项中的值会被视为不合法,操作过程中会被组件清除掉| |fallback-option|`false \| (value: string \| number) => SelectOption`|`value => ({ label: '' + value, value })`|在传入的选项中没有对应当前值的选项时,这个值应该对应的选项。如果设为 `false`,不会为找不到对应选项的值生成回退选项也不会显示它,未在选项中的值会被视为不合法,操作过程中会被组件清除掉|
|filterable|`boolean`|`false`|是否可以过滤| |filterable|`boolean`|`false`|是否可以过滤|
@ -38,7 +39,7 @@ menu-debug
|size|`'small' \| 'medium' \| 'large'`|`'medium'`|| |size|`'small' \| 'medium' \| 'large'`|`'medium'`||
|tag|`boolean`|`false`|是否可以创建新的选项,需要和 `filterable` 一起使用| |tag|`boolean`|`false`|是否可以创建新的选项,需要和 `filterable` 一起使用|
|theme|`'light' \| 'dark' \| string`|`undefined`|| |theme|`'light' \| 'dark' \| string`|`undefined`||
|value|`Array<string \| number> \| string \| number`|`false`|| |value|`Array<string \| number> \| string \| number \| null`|`undefined`||
|on-blur|`() => any`|选择器 Blur 时发出| |on-blur|`() => any`|选择器 Blur 时发出|
|on-create|`(label: string) => SelectOption`|`label => ({ label, value: label })`|在输入内容时如何创建一个选项。注意 `filter` 对这个生成的选项同样会生效。同时确保这个选项和其他选项的 `value` 不要有重复| |on-create|`(label: string) => SelectOption`|`label => ({ label, value: label })`|在输入内容时如何创建一个选项。注意 `filter` 对这个生成的选项同样会生效。同时确保这个选项和其他选项的 `value` 不要有重复|
|on-focus|`() => any`|选择器 Focus 时发出| |on-focus|`() => any`|选择器 Focus 时发出|

View File

@ -66,7 +66,7 @@
:multiple="multiple" :multiple="multiple"
size="medium" size="medium"
:filterable="filterable" :filterable="filterable"
:value="value" :value="mergedValue"
@menu-toggle-option="handleToggleOption" @menu-toggle-option="handleToggleOption"
@scroll="handleMenuScroll" @scroll="handleMenuScroll"
> >
@ -195,10 +195,14 @@ export default {
type: Array, type: Array,
required: true required: true
}, },
value: { defaultValue: {
type: [String, Number, Array], type: [String, Number, Array],
default: null default: null
}, },
value: {
type: [String, Number, Array],
default: undefined
},
placeholder: { placeholder: {
type: String, type: String,
default: undefined default: undefined
@ -313,6 +317,9 @@ export default {
} }
}, },
setup (props) { setup (props) {
const uncontrolledValueRef = ref(props.defaultValue)
const controlledValueRef = toRef(props, 'value')
const mergedValueRef = useMergedState(controlledValueRef, uncontrolledValueRef)
const patternRef = ref('') const patternRef = ref('')
const filteredOptionsRef = computed(() => filterOptions( const filteredOptionsRef = computed(() => filterOptions(
props.options, props.options,
@ -354,6 +361,8 @@ export default {
createdOptions: ref([]), createdOptions: ref([]),
beingCreatedOptions: ref([]), beingCreatedOptions: ref([]),
memoValOptMap: ref(new Map()), memoValOptMap: ref(new Map()),
uncontrolledValue: uncontrolledValueRef,
mergedValue: mergedValueRef,
followerRef followerRef
} }
}, },
@ -382,7 +391,7 @@ export default {
}, },
selectedOptions () { selectedOptions () {
if (this.multiple) { if (this.multiple) {
const { value: values } = this const { mergedValue: values } = this
if (!Array.isArray(values)) return [] if (!Array.isArray(values)) return []
const remote = this.remote const remote = this.remote
const { const {
@ -409,17 +418,17 @@ export default {
}, },
selectedOption () { selectedOption () {
if (!this.multiple) { if (!this.multiple) {
const { value, valOptMap, wrappedFallbackOption } = this const { mergedValue, valOptMap, wrappedFallbackOption } = this
if (value === null) return null if (mergedValue === null) return null
let selectedOption = null let selectedOption = null
if (valOptMap.has(value)) { if (valOptMap.has(mergedValue)) {
selectedOption = valOptMap.get(value) selectedOption = valOptMap.get(mergedValue)
} else if (this.remote) { } else if (this.remote) {
selectedOption = this.memoValOptMap.get(value) selectedOption = this.memoValOptMap.get(mergedValue)
} }
return ( return (
selectedOption || selectedOption ||
(wrappedFallbackOption && wrappedFallbackOption(value)) || (wrappedFallbackOption && wrappedFallbackOption(mergedValue)) ||
null null
) )
} }
@ -443,7 +452,7 @@ export default {
if (!this.mergedShow) return if (!this.mergedShow) return
this.$nextTick(this.syncPosition) this.$nextTick(this.syncPosition)
}, },
value () { mergedValue () {
if (!this.mergedShow) return if (!this.mergedShow) return
this.$nextTick(this.syncPosition) this.$nextTick(this.syncPosition)
} }
@ -461,6 +470,7 @@ export default {
} = this } = this
if (onChange) call(onChange, value) if (onChange) call(onChange, value)
if (onUpdateValue) call(onUpdateValue, value) if (onUpdateValue) call(onUpdateValue, value)
this.uncontrolledValue = value
nTriggerFormChange() nTriggerFormChange()
nTriggerFormInput() nTriggerFormInput()
}, },
@ -586,7 +596,7 @@ export default {
this.memoValOptMap.set(option.value, option) this.memoValOptMap.set(option.value, option)
} }
if (this.multiple) { if (this.multiple) {
const changedValue = this.createClearedMultipleSelectValue(this.value) const changedValue = this.createClearedMultipleSelectValue(this.mergedValue)
const index = changedValue.findIndex(value => value === option.value) const index = changedValue.findIndex(value => value === option.value)
if (~index) { if (~index) {
changedValue.splice(index, 1) changedValue.splice(index, 1)
@ -620,7 +630,7 @@ export default {
}, },
handleDeleteLastOption (e) { handleDeleteLastOption (e) {
if (!this.pattern.length) { if (!this.pattern.length) {
const changedValue = this.createClearedMultipleSelectValue(this.value) const changedValue = this.createClearedMultipleSelectValue(this.mergedValue)
if (Array.isArray(changedValue)) { if (Array.isArray(changedValue)) {
const poppedValue = changedValue.pop() const poppedValue = changedValue.pop()
const createdOptionIndex = this.getCreatedOptionIndex(poppedValue) const createdOptionIndex = this.getCreatedOptionIndex(poppedValue)
@ -636,7 +646,7 @@ export default {
) )
}, },
handlePatternInput (e) { handlePatternInput (e) {
const value = e.target.value const { value } = e.target
this.pattern = value this.pattern = value
const { onSearch, tag, remote } = this const { onSearch, tag, remote } = this
if (onSearch) { if (onSearch) {