Vue · Lifecycle
vite-doctor/vuelifecyclewarnSuggestion
Why it happens
DOM listeners are lifecycle resources. Keeping setup and disposal behind a composable makes repeated watcher runs, component unmounts, and composable scope disposal harder to drift apart.
Fix
Use VueUse useEventListener() for DOM listeners. In watcher callbacks, keep the returned stop handle in watcher cleanup when each watcher run owns a fresh listener.
Example
Use VueUse for watcher-owned listeners
Before
watch(active, (_value, _oldValue, onCleanup) => {
const el = document.querySelector('.target')
if (!el) return
const onEnd = () => el.classList.remove('active')
el.addEventListener('animationend', onEnd, { once: true })
onCleanup(() => el.removeEventListener('animationend', onEnd))
})
After
watch(active, (_value, _oldValue, onCleanup) => {
const el = document.querySelector('.target')
if (!el) return
const stop = useEventListener(el, 'animationend', () => {
el.classList.remove('active')
}, { once: true })
onCleanup(stop)
})
Verify the fix
Run only this rule after editing so the report stays focused on the diagnostic you are closing:
pnpm vite-doctor . --framework vue --rules vue/lifecycle/prefer-use-event-listener