mirror of https://github.com/vuejs/core.git
Merge 7eab641603
into 56be3dd4db
This commit is contained in:
commit
2c8e3a6a99
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
type VNode,
|
||||
computed,
|
||||
defineComponent,
|
||||
h,
|
||||
nextTick,
|
||||
|
@ -1409,6 +1410,51 @@ describe('vModel', () => {
|
|||
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
|
||||
test('equal value with a leading 0 should trigger update.', async () => {
|
||||
const setNum = function (this: any, value: any) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
type ObjectDirective,
|
||||
type VNode,
|
||||
nextTick,
|
||||
toRaw,
|
||||
warn,
|
||||
} from '@vue/runtime-core'
|
||||
import { addEventListener } from '../modules/events'
|
||||
|
@ -38,9 +39,15 @@ function onCompositionEnd(e: Event) {
|
|||
}
|
||||
|
||||
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<
|
||||
T & { [assignKey]: AssignerFn; _assigning?: boolean },
|
||||
T & {
|
||||
[assignKey]: AssignerFn
|
||||
[assignValueKey]: any
|
||||
[assigningKey]?: boolean
|
||||
},
|
||||
any,
|
||||
Modifiers
|
||||
>
|
||||
|
@ -210,16 +217,15 @@ export const vModelSelect: ModelDirective<HTMLSelectElement, 'number'> = {
|
|||
.map((o: HTMLOptionElement) =>
|
||||
number ? looseToNumber(getValue(o)) : getValue(o),
|
||||
)
|
||||
el[assignKey](
|
||||
el.multiple
|
||||
? isSetModel
|
||||
? new Set(selectedVal)
|
||||
: selectedVal
|
||||
: selectedVal[0],
|
||||
)
|
||||
el._assigning = true
|
||||
const value = (el[assignValueKey] = el.multiple
|
||||
? isSetModel
|
||||
? new Set(selectedVal)
|
||||
: selectedVal
|
||||
: selectedVal[0])
|
||||
el[assignKey](value)
|
||||
el[assigningKey] = true
|
||||
nextTick(() => {
|
||||
el._assigning = false
|
||||
el[assigningKey] = false
|
||||
})
|
||||
})
|
||||
el[assignKey] = getModelAssigner(vnode)
|
||||
|
@ -233,7 +239,7 @@ export const vModelSelect: ModelDirective<HTMLSelectElement, 'number'> = {
|
|||
el[assignKey] = getModelAssigner(vnode)
|
||||
},
|
||||
updated(el, { value }) {
|
||||
if (!el._assigning) {
|
||||
if (!el[assigningKey] || toRaw(value) !== el[assignValueKey]) {
|
||||
setSelected(el, value)
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue