mirror of https://github.com/vuejs/core.git
Merge 7eab641603
into 56be3dd4db
This commit is contained in:
commit
2c8e3a6a99
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
type VNode,
|
type VNode,
|
||||||
|
computed,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
h,
|
h,
|
||||||
nextTick,
|
nextTick,
|
||||||
|
@ -1409,6 +1410,51 @@ describe('vModel', () => {
|
||||||
expect(bar.selected).toEqual(true)
|
expect(bar.selected).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('multiple select (v-model has custom setter)', async () => {
|
||||||
|
const selected = ref([])
|
||||||
|
|
||||||
|
const multipleSelected = computed({
|
||||||
|
get() {
|
||||||
|
return selected.value
|
||||||
|
},
|
||||||
|
set(newVal) {
|
||||||
|
selected.value = newVal.slice(0, 1)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const setValue = (v: any) => {
|
||||||
|
multipleSelected.value = v
|
||||||
|
}
|
||||||
|
const component = defineComponent({
|
||||||
|
render() {
|
||||||
|
return [
|
||||||
|
withVModel(
|
||||||
|
h(
|
||||||
|
'select',
|
||||||
|
{
|
||||||
|
multiple: true,
|
||||||
|
'onUpdate:modelValue': setValue,
|
||||||
|
},
|
||||||
|
[h('option', { value: '1' }), h('option', { value: '2' })],
|
||||||
|
),
|
||||||
|
multipleSelected.value,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
})
|
||||||
|
render(h(component), root)
|
||||||
|
|
||||||
|
await nextTick()
|
||||||
|
const select = root.querySelector('select')
|
||||||
|
const [foo, bar] = root.querySelectorAll('option')
|
||||||
|
foo.selected = true
|
||||||
|
bar.selected = true
|
||||||
|
triggerEvent('change', select)
|
||||||
|
await nextTick()
|
||||||
|
expect(selected.value).toEqual(['1'])
|
||||||
|
expect(foo.selected).toEqual(true)
|
||||||
|
expect(bar.selected).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
// #10503
|
// #10503
|
||||||
test('equal value with a leading 0 should trigger update.', async () => {
|
test('equal value with a leading 0 should trigger update.', async () => {
|
||||||
const setNum = function (this: any, value: any) {
|
const setNum = function (this: any, value: any) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
type ObjectDirective,
|
type ObjectDirective,
|
||||||
type VNode,
|
type VNode,
|
||||||
nextTick,
|
nextTick,
|
||||||
|
toRaw,
|
||||||
warn,
|
warn,
|
||||||
} from '@vue/runtime-core'
|
} from '@vue/runtime-core'
|
||||||
import { addEventListener } from '../modules/events'
|
import { addEventListener } from '../modules/events'
|
||||||
|
@ -38,9 +39,15 @@ function onCompositionEnd(e: Event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const assignKey: unique symbol = Symbol('_assign')
|
const assignKey: unique symbol = Symbol('_assign')
|
||||||
|
const assignValueKey: unique symbol = Symbol('_value')
|
||||||
|
const assigningKey: unique symbol = Symbol('_assigning')
|
||||||
|
|
||||||
type ModelDirective<T, Modifiers extends string = string> = ObjectDirective<
|
type ModelDirective<T, Modifiers extends string = string> = ObjectDirective<
|
||||||
T & { [assignKey]: AssignerFn; _assigning?: boolean },
|
T & {
|
||||||
|
[assignKey]: AssignerFn
|
||||||
|
[assignValueKey]: any
|
||||||
|
[assigningKey]?: boolean
|
||||||
|
},
|
||||||
any,
|
any,
|
||||||
Modifiers
|
Modifiers
|
||||||
>
|
>
|
||||||
|
@ -210,16 +217,15 @@ export const vModelSelect: ModelDirective<HTMLSelectElement, 'number'> = {
|
||||||
.map((o: HTMLOptionElement) =>
|
.map((o: HTMLOptionElement) =>
|
||||||
number ? looseToNumber(getValue(o)) : getValue(o),
|
number ? looseToNumber(getValue(o)) : getValue(o),
|
||||||
)
|
)
|
||||||
el[assignKey](
|
const value = (el[assignValueKey] = el.multiple
|
||||||
el.multiple
|
? isSetModel
|
||||||
? isSetModel
|
? new Set(selectedVal)
|
||||||
? new Set(selectedVal)
|
: selectedVal
|
||||||
: selectedVal
|
: selectedVal[0])
|
||||||
: selectedVal[0],
|
el[assignKey](value)
|
||||||
)
|
el[assigningKey] = true
|
||||||
el._assigning = true
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
el._assigning = false
|
el[assigningKey] = false
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
el[assignKey] = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
|
@ -233,7 +239,7 @@ export const vModelSelect: ModelDirective<HTMLSelectElement, 'number'> = {
|
||||||
el[assignKey] = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
},
|
},
|
||||||
updated(el, { value }) {
|
updated(el, { value }) {
|
||||||
if (!el._assigning) {
|
if (!el[assigningKey] || toRaw(value) !== el[assignValueKey]) {
|
||||||
setSelected(el, value)
|
setSelected(el, value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue