JAVASCRIPT
Build a `useClickOutside` Composable in Vue 3
Learn to create a custom Vue 3 composable (`useClickOutside`) to detect clicks outside a specific DOM element, ideal for dropdowns, context menus, and popovers.
// composables/useClickOutside.js
import { onMounted, onUnmounted } from 'vue';
export function useClickOutside(targetRef, callback) {
if (!targetRef) {
console.warn('useClickOutside: targetRef is required.');
return;
}
const handleClickOutside = (event) => {
// Check if the click occurred outside the target element
if (targetRef.value && !targetRef.value.contains(event.target)) {
callback(event); // Invoke the callback if clicked outside
}
};
onMounted(() => {
// Attach the event listener when the component is mounted
document.addEventListener('click', handleClickOutside);
});
onUnmounted(() => {
// Remove the event listener when the component is unmounted to prevent memory leaks
document.removeEventListener('click', handleClickOutside);
});
}
// DropdownMenu.vue
<template>
<div class="dropdown" ref="dropdownRef">
<button @click="isOpen = !isOpen">Toggle Dropdown</button>
<div v-if="isOpen" class="dropdown-content">
<p>Item 1</p>
<p>Item 2</p>
<p>Item 3</p>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useClickOutside } from './composables/useClickOutside';
const dropdownRef = ref(null); // Create a ref to attach to the dropdown element
const isOpen = ref(false);
// Use the composable, passing the ref and a callback function
useClickOutside(dropdownRef, () => {
if (isOpen.value) {
isOpen.value = false; // Close the dropdown if clicked outside
console.log('Clicked outside dropdown!');
}
});
</script>
<style scoped>
/* Basic styling for the dropdown */
.dropdown {
position: relative;
display: inline-block;
margin-top: 20px;
}
.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;
margin-top: 5px;
border-radius: 4px;
}
</style>
How it works: Composables are reusable functions that encapsulate stateful logic in Vue 3's Composition API. This `useClickOutside` composable detects when a user clicks anywhere on the document outside of a specified element. It leverages `onMounted` and `onUnmounted` to properly add and remove a global click event listener, preventing memory leaks. It's ideal for implementing common UI patterns like closing dropdowns, sidebars, or modals when the user clicks away.