]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-dom): avoid unnecessary prop patch for checkbox (#11657)
authorAlex Liu <dsa1314@gmail.com>
Tue, 3 Sep 2024 13:10:18 +0000 (21:10 +0800)
committerGitHub <noreply@github.com>
Tue, 3 Sep 2024 13:10:18 +0000 (21:10 +0800)
close #11647

packages/runtime-dom/__tests__/patchProps.spec.ts
packages/runtime-dom/src/modules/props.ts

index 952508f8f912c6487d02bbf0ab5698ca48fa2408..304d9f9c136f0fe733cf278182585f21f1391e9b 100644 (file)
@@ -1,5 +1,12 @@
 import { patchProp } from '../src/patchProp'
-import { h, nextTick, ref, render } from '../src'
+import {
+  h,
+  nextTick,
+  ref,
+  render,
+  vModelCheckbox,
+  withDirectives,
+} from '../src'
 
 describe('runtime-dom: props patching', () => {
   test('basic', () => {
@@ -351,4 +358,40 @@ describe('runtime-dom: props patching', () => {
     expect(el.translate).toBeFalsy()
     expect(el.getAttribute('translate')).toBe('no')
   })
+
+  // #11647
+  test('should not trigger input mutation when `value` is `undefined`', async () => {
+    const fn = vi.fn()
+    const comp = {
+      setup() {
+        const checked = ref()
+        return () =>
+          withDirectives(
+            h('input', {
+              type: 'checkbox',
+              value: undefined,
+              'onUpdate:modelValue': (value: any) => {
+                checked.value = value
+              },
+            }),
+            [[vModelCheckbox, checked.value]],
+          )
+      },
+    }
+
+    const root = document.createElement('div')
+    render(h(comp), root)
+    document.body.append(root)
+
+    const el = root.children[0] as HTMLInputElement
+    const observer = new MutationObserver(fn)
+    observer.observe(el, {
+      attributes: true,
+    })
+
+    el.click()
+    await nextTick()
+
+    expect(fn).toBeCalledTimes(0)
+  })
 })
index 4dfcee6aee668ed65f99547dd1c4be026344ab53..93d45c9e1607f85da3fe37e2d160a716fed6a60f 100644 (file)
@@ -33,7 +33,14 @@ export function patchDOMProp(
     // compare against its attribute value instead.
     const oldValue =
       tag === 'OPTION' ? el.getAttribute('value') || '' : el.value
-    const newValue = value == null ? '' : String(value)
+    const newValue =
+      value == null
+        ? // #11647: value should be set as empty string for null and undefined,
+          // but <input type="checkbox"> should be set as 'on'.
+          el.type === 'checkbox'
+          ? 'on'
+          : ''
+        : String(value)
     if (oldValue !== newValue || !('_value' in el)) {
       el.value = newValue
     }