fix(components): [popper] trigger memory leak issue (#22763)

* fix(components): trigger memory leak issue

* fix: update test

* Update packages/components/popper/src/trigger.vue

---------

Co-authored-by: btea <2356281422@qq.com>
This commit is contained in:
Map1en
2025-11-13 23:46:09 +09:00
committed by GitHub
parent 37600dadd3
commit 3b6f377eb4
2 changed files with 38 additions and 5 deletions

View File

@@ -73,5 +73,30 @@ describe('<ElPopperTrigger />', () => {
await nextTick()
expect(onClick).toHaveBeenCalled()
})
it('should cleanup listeners when triggerRef changes', async () => {
const onClick = vi.fn()
const first = document.createElement('p')
const removeSpy = vi.spyOn(first, 'removeEventListener')
const addSpy = vi.spyOn(first, 'addEventListener')
wrapper = mountTrigger({
onClick,
virtualTriggering: true,
virtualRef: first,
})
await nextTick()
await wrapper.setProps({
virtualRef: {
getBoundingClientRect: () => {
return { top: 0, left: 0, right: 0, bottom: 0, width: 0, height: 0 }
},
},
})
await nextTick()
expect(addSpy).toHaveBeenCalledWith('click', onClick, false)
expect(removeSpy).toHaveBeenCalledWith('click', onClick, false)
})
})
})

View File

@@ -86,6 +86,19 @@ onMounted(() => {
(el, prevEl) => {
virtualTriggerAriaStopWatch?.()
virtualTriggerAriaStopWatch = undefined
if (isElement(prevEl)) {
TRIGGER_ELE_EVENTS.forEach((eventName) => {
const handler = props[eventName]
if (handler) {
;(prevEl as HTMLElement).removeEventListener(
eventName.slice(2).toLowerCase(),
handler,
['onFocus', 'onBlur'].includes(eventName)
)
}
})
}
if (isElement(el)) {
TRIGGER_ELE_EVENTS.forEach((eventName) => {
const handler = props[eventName]
@@ -95,11 +108,6 @@ onMounted(() => {
handler,
['onFocus', 'onBlur'].includes(eventName)
)
;(prevEl as HTMLElement)?.removeEventListener?.(
eventName.slice(2).toLowerCase(),
handler,
['onFocus', 'onBlur'].includes(eventName)
)
}
})
if (isFocusable(el as HTMLElement)) {