Skip to content

Commit ea943af

Browse files
authored
fix(runtime-dom): prevent unnecessary updates in v-model checkbox when value is unchanged (#12146)
close #12144
1 parent d82fa61 commit ea943af

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ export const vModelCheckbox: ModelDirective<HTMLInputElement> = {
160160

161161
function setChecked(
162162
el: HTMLInputElement,
163-
{ value }: DirectiveBinding,
163+
{ value, oldValue }: DirectiveBinding,
164164
vnode: VNode,
165165
) {
166166
// store the v-model value on the element so it can be accessed by the
@@ -173,6 +173,7 @@ function setChecked(
173173
} else if (isSet(value)) {
174174
checked = value.has(vnode.props!.value)
175175
} else {
176+
if (value === oldValue) return
176177
checked = looseEqual(value, getCheckboxValue(el, true))
177178
}
178179

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import path from 'node:path'
2+
import { setupPuppeteer } from './e2eUtils'
3+
4+
const { page, click, isChecked } = setupPuppeteer()
5+
import { nextTick } from 'vue'
6+
7+
beforeEach(async () => {
8+
await page().addScriptTag({
9+
path: path.resolve(__dirname, '../../dist/vue.global.js'),
10+
})
11+
await page().setContent(`<div id="app"></div>`)
12+
})
13+
14+
// #12144
15+
test('checkbox click with v-model', async () => {
16+
await page().evaluate(() => {
17+
const { createApp } = (window as any).Vue
18+
createApp({
19+
template: `
20+
<label>
21+
<input
22+
id="first"
23+
type="checkbox"
24+
v-model="first"/>
25+
First
26+
</label>
27+
<br>
28+
<label>
29+
<input
30+
id="second"
31+
type="checkbox"
32+
v-model="second"
33+
@click="secondClick"/>
34+
Second
35+
</label>
36+
`,
37+
data() {
38+
return {
39+
first: true,
40+
second: false,
41+
}
42+
},
43+
methods: {
44+
secondClick(this: any) {
45+
this.first = false
46+
},
47+
},
48+
}).mount('#app')
49+
})
50+
51+
expect(await isChecked('#first')).toBe(true)
52+
expect(await isChecked('#second')).toBe(false)
53+
await click('#second')
54+
await nextTick()
55+
expect(await isChecked('#first')).toBe(false)
56+
expect(await isChecked('#second')).toBe(true)
57+
})

0 commit comments

Comments
 (0)