]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(v-model): avoid overwriting number input with same value (#7004)
author白雾三语 <32354856+baiwusanyu-c@users.noreply.github.com>
Thu, 9 Nov 2023 07:14:38 +0000 (15:14 +0800)
committerGitHub <noreply@github.com>
Thu, 9 Nov 2023 07:14:38 +0000 (15:14 +0800)
close #7003

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

index 73b8f18afc0806c36aba82de7e69562a6881b8a1..acf1b40b6969f0995b34b7fc64fc815a50970cb8 100644 (file)
@@ -101,6 +101,61 @@ describe('vModel', () => {
     expect(data.value).toEqual(1)
   })
 
+  // #7003
+  it('should work with number input and be able to update rendering correctly', async () => {
+    const setValue1 = function (this: any, value: any) {
+      this.value1 = value
+    }
+    const setValue2 = function (this: any, value: any) {
+      this.value2 = value
+    }
+    const component = defineComponent({
+      data() {
+        return { value1: 1.002, value2: 1.002 }
+      },
+      render() {
+        return [
+          withVModel(
+            h('input', {
+              id: 'input_num1',
+              type: 'number',
+              'onUpdate:modelValue': setValue1.bind(this)
+            }),
+            this.value1
+          ),
+          withVModel(
+            h('input', {
+              id: 'input_num2',
+              type: 'number',
+              'onUpdate:modelValue': setValue2.bind(this)
+            }),
+            this.value2
+          )
+        ]
+      }
+    })
+    render(h(component), root)
+    const data = root._vnode.component.data
+
+    const inputNum1 = root.querySelector('#input_num1')!
+    expect(inputNum1.value).toBe('1.002')
+
+    const inputNum2 = root.querySelector('#input_num2')!
+    expect(inputNum2.value).toBe('1.002')
+
+    inputNum1.value = '1.00'
+    triggerEvent('input', inputNum1)
+    await nextTick()
+    expect(data.value1).toBe(1)
+
+    inputNum2.value = '1.00'
+    triggerEvent('input', inputNum2)
+    await nextTick()
+    expect(data.value2).toBe(1)
+
+    expect(inputNum1.value).toBe('1.00')
+  })
+
   it('should work with multiple listeners', async () => {
     const spy = vi.fn()
     const component = defineComponent({
index 89cd5f9d49f1bd72a090abbdee7822313f1304f0..1bc4e76dfbc4e9e3ff13caab83336d3013389fad 100644 (file)
@@ -83,24 +83,25 @@ export const vModelText: ModelDirective<
     el[assignKey] = getModelAssigner(vnode)
     // avoid clearing unresolved text. #2302
     if ((el as any).composing) return
+
+    const elValue =
+      number || el.type === 'number' ? looseToNumber(el.value) : el.value
+    const newValue = value == null ? '' : value
+
+    if (elValue === newValue) {
+      return
+    }
+
     if (document.activeElement === el && el.type !== 'range') {
       if (lazy) {
         return
       }
-      if (trim && el.value.trim() === value) {
-        return
-      }
-      if (
-        (number || el.type === 'number') &&
-        looseToNumber(el.value) === value
-      ) {
+      if (trim && el.value.trim() === newValue) {
         return
       }
     }
-    const newValue = value == null ? '' : value
-    if (el.value !== newValue) {
-      el.value = newValue
-    }
+
+    el.value = newValue
   }
 }