Skip to content

Commit b4eb7e3

Browse files
authored
fix(runtime-core): improve dedupe listeners when attr fallthrough (#4912)
fix #4859
1 parent 04e5835 commit b4eb7e3

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts

+41-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
createBlock,
1212
FunctionalComponent,
1313
createCommentVNode,
14-
Fragment
14+
Fragment,
15+
withModifiers
1516
} from '@vue/runtime-dom'
1617
import { PatchFlags } from '@vue/shared/src'
1718

@@ -383,6 +384,45 @@ describe('attribute fallthrough', () => {
383384
expect(`Extraneous non-emits event listeners`).toHaveBeenWarned()
384385
})
385386

387+
it('should dedupe same listeners when $attrs is used during render', () => {
388+
const click = jest.fn()
389+
const count = ref(0)
390+
391+
function inc() {
392+
count.value++
393+
click()
394+
}
395+
396+
const Parent = {
397+
render() {
398+
return h(Child, { onClick: inc })
399+
}
400+
}
401+
402+
const Child = defineComponent({
403+
render() {
404+
return h(
405+
'div',
406+
mergeProps(
407+
{
408+
onClick: withModifiers(() => {}, ['prevent', 'stop'])
409+
},
410+
this.$attrs
411+
)
412+
)
413+
}
414+
})
415+
416+
const root = document.createElement('div')
417+
document.body.appendChild(root)
418+
render(h(Parent), root)
419+
420+
const node = root.children[0] as HTMLElement
421+
node.dispatchEvent(new CustomEvent('click'))
422+
expect(click).toHaveBeenCalledTimes(1)
423+
expect(count.value).toBe(1)
424+
})
425+
386426
it('should not warn when $attrs is used during render', () => {
387427
const Parent = {
388428
render() {

packages/runtime-core/src/vnode.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,10 @@ export function mergeProps(...args: (Data & VNodeProps)[]) {
791791
} else if (isOn(key)) {
792792
const existing = ret[key]
793793
const incoming = toMerge[key]
794-
if (existing !== incoming) {
794+
if (
795+
existing !== incoming &&
796+
!(isArray(existing) && existing.includes(incoming))
797+
) {
795798
ret[key] = existing
796799
? [].concat(existing as any, incoming as any)
797800
: incoming

0 commit comments

Comments
 (0)