JAVASCRIPT
Building a Reusable Click-Outside Detector Composable in Vue 3
Develop a powerful Vue 3 Composition API composable to detect clicks outside a specified element, ideal for closing dropdowns, modals, or context menus programmatically.
// composables/useClickOutside.js
import { onMounted, onUnmounted } from 'vue';
export function useClickOutside(elementRef, callback) {
const handleClick = (event) => {
if (elementRef.value && !elementRef.value.contains(event.target)) {
callback(event);
}
};
onMounted(() => {
document.addEventListener('click', handleClick);
});
onUnmounted(() => {
document.removeEventListener('click', handleClick);
});
}
// MyComponent.vue
<template>
<div style="position: relative;">
<button @click="isOpen = !isOpen">Toggle Dropdown</button>
<div v-if="isOpen" ref="dropdownRef" class="dropdown-content">
<p>Dropdown Item 1</p>
<p>Dropdown Item 2</p>
</div>
</div>
<p>Click anywhere outside the dropdown to close it.</p>
</template>
<script setup>
import { ref } from 'vue';
import { useClickOutside } from './composables/useClickOutside';
const isOpen = ref(false);
const dropdownRef = ref(null);
useClickOutside(dropdownRef, () => {
isOpen.value = false;
});
</script>
<style scoped>
.dropdown-content {
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
padding: 12px 16px;
z-index: 1;
border-radius: 4px;
margin-top: 5px;
}
</style>
How it works: This snippet provides a reusable Vue 3 composable, `useClickOutside`, that simplifies detecting clicks outside a specific element. It takes a `ref` to the target element and a callback function. Upon mounting, it attaches a global click listener to the document. If a click occurs outside the `elementRef`, the callback is executed. The listener is automatically cleaned up when the component unmounts using `onUnmounted`, preventing memory leaks. This pattern is ideal for common UI elements like dropdowns or modals that need to close when the user interacts elsewhere.