]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(v-model): handle number modifier on change (#13959)
authorrzzf <cszhjh@gmail.com>
Wed, 5 Nov 2025 09:11:35 +0000 (17:11 +0800)
committerGitHub <noreply@github.com>
Wed, 5 Nov 2025 09:11:35 +0000 (17:11 +0800)
close #13958

packages/runtime-dom/__tests__/directives/vModel.spec.ts
packages/runtime-dom/src/directives/vModel.ts

index d9a7790e0f622318bdc2444fb588e4efdcbfd91e..c3c420f407a190526208c580fed03e1f808ee9d1 100644 (file)
@@ -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)
index 5057e16d472bc59304b2bb386e96b53934e6cf92..3b446e320c5732451b16eb2b00440f0e4cf31926 100644 (file)
@@ -45,6 +45,12 @@ type ModelDirective<T, Modifiers extends string = string> = 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) {