useEventListener
A composable for handling DOM events with automatic cleanup on component unmount.
Usage
The useEventListener composable attaches event listeners to DOM elements (Window, Document, or HTMLElement) with automatic cleanup when the component is unmounted. It supports reactive targets, multiple events, and multiple handlers.
Why wrap addEventListener? Native addEventListener has no awareness of Vue’s effectScope lifecycle — listeners you add won’t be removed when the scope is disposed. useEventListener integrates onScopeDispose for automatic cleanup, supports reactive targets and events that re-register on change, and provides type-safe overloads for Window, Document, and HTMLElement targets.
<script setup lang="ts">
import { useEventListener, useWindowEventListener, useDocumentEventListener } from '@vuetify/v0'
import { ref, useTemplateRef } from 'vue'
// Track window dimensions
const windowSize = ref({ width: window.innerWidth, height: window.innerHeight })
useWindowEventListener('resize', () => {
windowSize.value = {
width: window.innerWidth,
height: window.innerHeight
}
})
// Handle keyboard shortcuts
useDocumentEventListener('keydown', (e) => {
if (e.ctrlKey && e.key === 's') {
e.preventDefault()
console.log('Save shortcut triggered')
}
})
// Element-specific listener
const button = useTemplateRef('button')
useEventListener(button, 'click', () => {
console.log('Button clicked!')
})
</script>
<template>
<div>
<p>Window: {{ windowSize.width }}x{{ windowSize.height }}</p>
<button ref="button">Click me</button>
</div>
</template>Architecture
useEventListener is the foundational event composable that others build upon:
Reactivity
| Property/Method | Reactive | Notes |
|---|---|---|
target | Accepts MaybeRefOrGetter, watched for changes | |
event | Accepts MaybeRefOrGetter, watched for changes | |
listener | Accepts MaybeRef, watched for changes | |
options | Accepts MaybeRefOrGetter, watched for changes |
Reactive inputs All parameters accept reactive values. When any input changes, listeners are automatically re-registered.
SSR safety useWindowEventListener and useDocumentEventListener are SSR-safe — they check IN_BROWSER and return a no-op cleanup on the server. Raw access to window or document in the listener body (e.g. window.innerWidth) is not guarded for you.
Examples
FAQ
When the target is dynamic (a ref, getter, or window/document), when you want one call site for setup and automatic teardown, or when the event name itself is reactive. Native addEventListener has no effectScope awareness, so its listeners outlive scope disposal; useEventListener wires onScopeDispose for you.
Yes — useWindowEventListener and useDocumentEventListener check IN_BROWSER and return a no-op cleanup on the server. Raw window/document access inside the listener body (e.g. window.innerWidth) is not guarded for you; wrap that yourself.
Yes. The second argument accepts an array of event names — useEventListener(el, ['mouseenter', 'mouseleave'], cb) — and the same handler runs for each.