From 71066b5afed7d3707b8ec9a6313dbdbd1adad45e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=88=98=28liulinboyi=29?= <814921718@qq.com> Date: Fri, 13 May 2022 07:52:16 +0800 Subject: [PATCH] fix(v-model): fix case where .trim and .number modifiers are used together (#5842) fix #5839 --- .../__tests__/componentEmits.spec.ts | 31 +++++++++++++++++++ packages/runtime-core/src/componentEmits.ts | 3 +- .../__tests__/directives/vModel.spec.ts | 26 +++++++++++++++- packages/runtime-dom/src/directives/vModel.ts | 3 +- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/__tests__/componentEmits.spec.ts b/packages/runtime-core/__tests__/componentEmits.spec.ts index 053d8714..f22be2de 100644 --- a/packages/runtime-core/__tests__/componentEmits.spec.ts +++ b/packages/runtime-core/__tests__/componentEmits.spec.ts @@ -355,6 +355,37 @@ describe('component: emit', () => { expect(fn2).toHaveBeenCalledWith('two') }) + test('.trim and .number modifiers should work with v-model on component', () => { + const Foo = defineComponent({ + render() {}, + created() { + this.$emit('update:modelValue', ' +01.2 ') + this.$emit('update:foo', ' 1 ') + } + }) + + const fn1 = jest.fn() + const fn2 = jest.fn() + + const Comp = () => + h(Foo, { + modelValue: null, + modelModifiers: { trim: true, number: true }, + 'onUpdate:modelValue': fn1, + + foo: null, + fooModifiers: { trim: true, number: true }, + 'onUpdate:foo': fn2 + }) + + render(h(Comp), nodeOps.createElement('div')) + + expect(fn1).toHaveBeenCalledTimes(1) + expect(fn1).toHaveBeenCalledWith(1.2) + expect(fn2).toHaveBeenCalledTimes(1) + expect(fn2).toHaveBeenCalledWith(1) + }) + test('isEmitListener', () => { const options = { click: null, diff --git a/packages/runtime-core/src/componentEmits.ts b/packages/runtime-core/src/componentEmits.ts index 3983e588..68393c80 100644 --- a/packages/runtime-core/src/componentEmits.ts +++ b/packages/runtime-core/src/componentEmits.ts @@ -122,7 +122,8 @@ export function emit( const { number, trim } = props[modifiersKey] || EMPTY_OBJ if (trim) { args = rawArgs.map(a => a.trim()) - } else if (number) { + } + if (number) { args = rawArgs.map(toNumber) } } diff --git a/packages/runtime-dom/__tests__/directives/vModel.spec.ts b/packages/runtime-dom/__tests__/directives/vModel.spec.ts index a192e930..c682fd5b 100644 --- a/packages/runtime-dom/__tests__/directives/vModel.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vModel.spec.ts @@ -201,7 +201,7 @@ describe('vModel', () => { it('should support modifiers', async () => { const component = defineComponent({ data() { - return { number: null, trim: null, lazy: null } + return { number: null, trim: null, lazy: null, trimNumber: null } }, render() { return [ @@ -229,6 +229,19 @@ describe('vModel', () => { trim: true } ), + withVModel( + h('input', { + class: 'trim-number', + 'onUpdate:modelValue': (val: any) => { + this.trimNumber = val + } + }), + this.trimNumber, + { + trim: true, + number: true + } + ), withVModel( h('input', { class: 'lazy', @@ -248,6 +261,7 @@ describe('vModel', () => { const number = root.querySelector('.number') const trim = root.querySelector('.trim') + const trimNumber = root.querySelector('.trim-number') const lazy = root.querySelector('.lazy') const data = root._vnode.component.data @@ -261,6 +275,16 @@ describe('vModel', () => { await nextTick() expect(data.trim).toEqual('hello, world') + trimNumber.value = ' 1 ' + triggerEvent('input', trimNumber) + await nextTick() + expect(data.trimNumber).toEqual(1) + + trimNumber.value = ' +01.2 ' + triggerEvent('input', trimNumber) + await nextTick() + expect(data.trimNumber).toEqual(1.2) + lazy.value = 'foo' triggerEvent('change', lazy) await nextTick() diff --git a/packages/runtime-dom/src/directives/vModel.ts b/packages/runtime-dom/src/directives/vModel.ts index 3d05e9fa..1a14decd 100644 --- a/packages/runtime-dom/src/directives/vModel.ts +++ b/packages/runtime-dom/src/directives/vModel.ts @@ -52,7 +52,8 @@ export const vModelText: ModelDirective< let domValue: string | number = el.value if (trim) { domValue = domValue.trim() - } else if (castToNumber) { + } + if (castToNumber) { domValue = toNumber(domValue) } el._assign(domValue)