diff --git a/packages/runtime-dom/__tests__/directives/vModel.spec.ts b/packages/runtime-dom/__tests__/directives/vModel.spec.ts index d9a7790e0f6..c3c420f407a 100644 --- a/packages/runtime-dom/__tests__/directives/vModel.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vModel.spec.ts @@ -345,6 +345,9 @@ describe('vModel', () => { triggerEvent('input', number) await nextTick() expect(data.number).toEqual(1.2) + triggerEvent('change', number) + await nextTick() + expect(number.value).toEqual('1.2') trim.value = ' hello, world ' triggerEvent('input', trim) diff --git a/packages/runtime-dom/src/directives/vModel.ts b/packages/runtime-dom/src/directives/vModel.ts index 5057e16d472..3b446e320c5 100644 --- a/packages/runtime-dom/src/directives/vModel.ts +++ b/packages/runtime-dom/src/directives/vModel.ts @@ -45,6 +45,12 @@ type ModelDirective = ObjectDirective< Modifiers > +function castValue(value: string, trim?: boolean, number?: boolean | null) { + if (trim) value = value.trim() + if (number) value = looseToNumber(value) + return value +} + // We are exporting the v-model runtime directly as vnode hooks so that it can // be tree-shaken in case v-model is never used. export const vModelText: ModelDirective< @@ -57,18 +63,11 @@ export const vModelText: ModelDirective< number || (vnode.props && vnode.props.type === 'number') addEventListener(el, lazy ? 'change' : 'input', e => { if ((e.target as any).composing) return - let domValue: string | number = el.value - if (trim) { - domValue = domValue.trim() - } - if (castToNumber) { - domValue = looseToNumber(domValue) - } - el[assignKey](domValue) + el[assignKey](castValue(el.value, trim, castToNumber)) }) - if (trim) { + if (trim || castToNumber) { addEventListener(el, 'change', () => { - el.value = el.value.trim() + el.value = castValue(el.value, trim, castToNumber) }) } if (!lazy) {