From 3d29ba863b89fd90dabd0856c0507eacdf5fef22 Mon Sep 17 00:00:00 2001
From: zrh122 <46116414+zrh122@users.noreply.github.com>
Date: Thu, 5 Aug 2021 17:21:12 +0800
Subject: [PATCH] fix(v-on): add removing all dom event listeners when vnode
destroyed (#10085)
---
src/platforms/web/runtime/modules/events.js | 8 +++--
.../component/component-keep-alive.spec.js | 32 +++++++++++++++++++
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/src/platforms/web/runtime/modules/events.js b/src/platforms/web/runtime/modules/events.js
index ecb08af3..3c60fd5d 100644
--- a/src/platforms/web/runtime/modules/events.js
+++ b/src/platforms/web/runtime/modules/events.js
@@ -5,6 +5,7 @@ import { updateListeners } from 'core/vdom/helpers/index'
import { isIE, isFF, supportsPassive, isUsingMicroTask } from 'core/util/index'
import { RANGE_TOKEN, CHECKBOX_RADIO_TOKEN } from 'web/compiler/directives/model'
import { currentFlushTimestamp } from 'core/observer/scheduler'
+import { emptyNode } from 'core/vdom/patch'
// normalize v-model event tokens that can only be determined at runtime.
// it's important to place the event as the first in the array because
@@ -108,7 +109,9 @@ function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
}
const on = vnode.data.on || {}
const oldOn = oldVnode.data.on || {}
- target = vnode.elm
+ // vnode is empty when removing all listeners,
+ // and use old vnode dom element
+ target = vnode.elm || oldVnode.elm
normalizeEvents(on)
updateListeners(on, oldOn, add, remove, createOnceHandler, vnode.context)
target = undefined
@@ -116,5 +119,6 @@ function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
export default {
create: updateDOMListeners,
- update: updateDOMListeners
+ update: updateDOMListeners,
+ destroy: (vnode: VNodeWithData) => updateDOMListeners(vnode, emptyNode)
}
diff --git a/test/unit/features/component/component-keep-alive.spec.js b/test/unit/features/component/component-keep-alive.spec.js
index c8734958..9d30d2c7 100644
--- a/test/unit/features/component/component-keep-alive.spec.js
+++ b/test/unit/features/component/component-keep-alive.spec.js
@@ -1249,5 +1249,37 @@ describe('Component keep-alive', () => {
}).then(done)
}
})
+
+ // #10083
+ it('should not attach event handler repeatedly', done => {
+ const vm = new Vue({
+ template: `
+
+
+
+ `,
+ data: { showBtn: true, n: 0 },
+ methods: {
+ add () {
+ this.n++
+ }
+ },
+ components: {
+ btn: { template: '' }
+ }
+ }).$mount()
+
+ const btn = vm.$el
+ expect(vm.n).toBe(0)
+ btn.click()
+ expect(vm.n).toBe(1)
+ vm.showBtn = false
+ waitForUpdate(() => {
+ vm.showBtn = true
+ }).then(() => {
+ btn.click()
+ expect(vm.n).toBe(2)
+ }).then(done)
+ })
}
})