diff --git a/demo/documentation/components/transfer/enUS/index.demo-entry.md b/demo/documentation/components/transfer/enUS/index.demo-entry.md index e04d0f57c..b14e051de 100644 --- a/demo/documentation/components/transfer/enUS/index.demo-entry.md +++ b/demo/documentation/components/transfer/enUS/index.demo-entry.md @@ -13,12 +13,11 @@ size filterable ``` - - ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | +| default-value | `Array \| null` | `null` | | | disabled | `boolean` | `true` | | | filterable | `boolean` | `false` | | | filter | `(pattern: string, option: TransferOption, from: 'source' \| 'target') => boolean` | A basic label string match function | | @@ -29,7 +28,7 @@ filterable | target-filter-placeholder | `string` | `undefined` | | | target-title | `string` | `'Target'` | | | theme | `'light' \| 'dark' \| string` | `undefined` | | -| value | `Array` | `null` | | +| value | `Array \| null` | `undefined` | | | on-update:value | `(value: Array) => any` | `undefined` | | | virtual-scroll | `boolean` | `false` | If use virtual scroll on transfer. If set to `true` it can handles large data (and turn transfer animation off) | diff --git a/demo/documentation/components/transfer/zhCN/index.demo-entry.md b/demo/documentation/components/transfer/zhCN/index.demo-entry.md index c50cc2b0b..ee521ea66 100644 --- a/demo/documentation/components/transfer/zhCN/index.demo-entry.md +++ b/demo/documentation/components/transfer/zhCN/index.demo-entry.md @@ -17,6 +17,7 @@ filterable | 名称 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | +| default-value | `Array \| null` | `null` | | | disabled | `boolean` | `true` | | | filterable | `boolean` | `false` | | | filter | `(pattern: string, option: TransferOption, from: 'source' \| 'target') => boolean` | 一个简单的标签字符串匹配函数 | | @@ -27,7 +28,7 @@ filterable | target-filter-placeholder | `string` | `undefined` | | | target-title | `string` | `'目标项'` | | | theme | `'light' \| 'dark' \| string` | `undefined` | | -| value | `Array` | `null` | | +| value | `Array \| null` | `undefined` | | | on-update:value | `(value: Array) => any` | `undefined` | | | virtual-scroll | `boolean` | `false` | If use virtual scroll on transfer. If set to `true` it can handles large data (and turn transfer animation off) | diff --git a/src/transfer/src/Transfer.vue b/src/transfer/src/Transfer.vue index fa4f295ff..1b8424c9b 100644 --- a/src/transfer/src/Transfer.vue +++ b/src/transfer/src/Transfer.vue @@ -260,6 +260,10 @@ export default { }, props: { value: { + type: Array, + default: undefined + }, + defaultValue: { type: Array, default: null }, @@ -346,15 +350,16 @@ export default { } }, methods: { - doUpdateValue (...args) { + doUpdateValue (value) { const { 'onUpdate:value': onUpdateValue, onChange, nTriggerFormInput, nTriggerFormChange } = this - if (onUpdateValue) call(onUpdateValue, ...args) - if (onChange) call(onChange, ...args) + if (onUpdateValue) call(onUpdateValue, value) + if (onChange) call(onChange, value) + this.uncontrolledValue = value nTriggerFormInput() nTriggerFormChange() }, @@ -399,13 +404,13 @@ export default { } }, handleToTgtClick () { - this.doUpdateValue(this.srcCheckedValues.concat(this.value || [])) + this.doUpdateValue(this.srcCheckedValues.concat(this.mergedValue || [])) this.srcCheckedValues = [] }, handleToSrcClick () { const tgtCheckedValueSet = new Set(this.tgtCheckedValues) this.doUpdateValue( - (this.value || []).filter((v) => !tgtCheckedValueSet.has(v)) + (this.mergedValue || []).filter((v) => !tgtCheckedValueSet.has(v)) ) this.tgtCheckedValues = [] }, diff --git a/src/transfer/src/data-utils.js b/src/transfer/src/data-utils.js index 93159fa1d..c6dc120ef 100644 --- a/src/transfer/src/data-utils.js +++ b/src/transfer/src/data-utils.js @@ -1,19 +1,25 @@ -import { ref, computed } from 'vue' -import { useMemo } from 'vooks' +import { ref, computed, toRef } from 'vue' +import { useMemo, useMergedState } from 'vooks' export function data (props) { + const uncontrolledValueRef = ref(props.defaultValue) + const controlledValueRef = toRef(props, 'value') + const mergedValueRef = useMergedState( + controlledValueRef, + uncontrolledValueRef + ) const optMapRef = computed(() => { const map = new Map() ;(props.options || []).forEach((opt) => map.set(opt.value, opt)) return map }) - const tgtValueSetRef = computed(() => new Set(props.value || [])) + const tgtValueSetRef = computed(() => new Set(mergedValueRef.value || [])) const srcOptsRef = computed(() => props.options.filter((option) => !tgtValueSetRef.value.has(option.value)) ) const tgtOptsRef = computed(() => { const optMap = optMapRef.value - return (props.value || []).map((v) => optMap.get(v)) + return (mergedValueRef.value || []).map((v) => optMap.get(v)) }) const srcPatternRef = ref('') const tgtPatternRef = ref('') @@ -121,6 +127,8 @@ export function data (props) { isInputingRef.value = false } return { + uncontrolledValue: uncontrolledValueRef, + mergedValue: mergedValueRef, avlSrcValueSet: avlSrcValueSetRef, avlTgtValueSet: avlTgtValueSetRef, tgtOpts: tgtOptsRef, diff --git a/vue3.md b/vue3.md index bb9b32569..9bc6f3cb2 100644 --- a/vue3.md +++ b/vue3.md @@ -303,6 +303,8 @@ - `v-model` => `v-model:value` - deprecate - `on-change` => `on-update:value` + - new + - `default-value` prop - [x] tree - break - `v-model` => `v-model:selected-keys`