Selaa lähdekoodia

fix(runtime-dom): prevent unnecessary updates in v-model checkbox when value is unchanged (#12146)

close #12144
Tycho 1 vuosi sitten
vanhempi
commit
ea943afe40

+ 2 - 1
packages/runtime-dom/src/directives/vModel.ts

@@ -160,7 +160,7 @@ export const vModelCheckbox: ModelDirective<HTMLInputElement> = {
 
 function setChecked(
   el: HTMLInputElement,
-  { value }: DirectiveBinding,
+  { value, oldValue }: DirectiveBinding,
   vnode: VNode,
 ) {
   // store the v-model value on the element so it can be accessed by the
@@ -173,6 +173,7 @@ function setChecked(
   } else if (isSet(value)) {
     checked = value.has(vnode.props!.value)
   } else {
+    if (value === oldValue) return
     checked = looseEqual(value, getCheckboxValue(el, true))
   }
 

+ 57 - 0
packages/vue/__tests__/e2e/vModel.spec.ts

@@ -0,0 +1,57 @@
+import path from 'node:path'
+import { setupPuppeteer } from './e2eUtils'
+
+const { page, click, isChecked } = setupPuppeteer()
+import { nextTick } from 'vue'
+
+beforeEach(async () => {
+  await page().addScriptTag({
+    path: path.resolve(__dirname, '../../dist/vue.global.js'),
+  })
+  await page().setContent(`<div id="app"></div>`)
+})
+
+// #12144
+test('checkbox click with v-model', async () => {
+  await page().evaluate(() => {
+    const { createApp } = (window as any).Vue
+    createApp({
+      template: `
+      <label>
+        <input 
+          id="first"
+          type="checkbox"
+          v-model="first"/>
+        First
+      </label>
+      <br>  
+      <label>
+        <input
+          id="second"
+          type="checkbox"
+          v-model="second"      
+          @click="secondClick"/>    
+          Second
+      </label> 
+        `,
+      data() {
+        return {
+          first: true,
+          second: false,
+        }
+      },
+      methods: {
+        secondClick(this: any) {
+          this.first = false
+        },
+      },
+    }).mount('#app')
+  })
+
+  expect(await isChecked('#first')).toBe(true)
+  expect(await isChecked('#second')).toBe(false)
+  await click('#second')
+  await nextTick()
+  expect(await isChecked('#first')).toBe(false)
+  expect(await isChecked('#second')).toBe(true)
+})