From c3ce9fe3d8fc27d864ce7148cd36da882cfc21ab Mon Sep 17 00:00:00 2001 From: Alex Liu Date: Tue, 3 Sep 2024 21:10:18 +0800 Subject: [PATCH] fix(runtime-dom): avoid unnecessary prop patch for checkbox (#11657) close #11647 --- .../runtime-dom/__tests__/patchProps.spec.ts | 45 ++++++++++++++++++- packages/runtime-dom/src/modules/props.ts | 9 +++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/packages/runtime-dom/__tests__/patchProps.spec.ts b/packages/runtime-dom/__tests__/patchProps.spec.ts index 952508f8f91..304d9f9c136 100644 --- a/packages/runtime-dom/__tests__/patchProps.spec.ts +++ b/packages/runtime-dom/__tests__/patchProps.spec.ts @@ -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) + }) }) diff --git a/packages/runtime-dom/src/modules/props.ts b/packages/runtime-dom/src/modules/props.ts index 4dfcee6aee6..93d45c9e160 100644 --- a/packages/runtime-dom/src/modules/props.ts +++ b/packages/runtime-dom/src/modules/props.ts @@ -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 should be set as 'on'. + el.type === 'checkbox' + ? 'on' + : '' + : String(value) if (oldValue !== newValue || !('_value' in el)) { el.value = newValue }