JAVASCRIPT
Create a Vue 3 Click Outside Directive
Implement a custom Vue 3 directive (`v-click-outside`) to detect clicks outside a specific element, useful for closing dropdowns or modals.
// directives/vClickOutside.js
export const vClickOutside = {
beforeMount(el, binding) {
el.__vueClickOutside__ = (event) => {
// Check if the click was outside the element and not on the element itself
if (!(el === event.target || el.contains(event.target))) {
// Call the provided method
binding.value(event);
}
};
document.addEventListener('click', el.__vueClickOutside__);
},
unmounted(el) {
document.removeEventListener('click', el.__vueClickOutside__);
delete el.__vueClickOutside__;
},
};
// main.js (or wherever you register global directives)
// import { createApp } from 'vue';
// import App from './App.vue';
// import { vClickOutside } from './directives/vClickOutside';
//
// const app = createApp(App);
// app.directive('click-outside', vClickOutside);
// app.mount('#app');
// App.vue (example usage)
<template>
<div>
<button @click="showDropdown = !showDropdown">Toggle Dropdown</button>
<div v-if="showDropdown" v-click-outside="closeDropdown" class="dropdown-content">
<p>This is a dropdown menu.</p>
<p>Click outside to close it.</p>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
// If registered globally in main.js, no need to import here
// import { vClickOutside } from './directives/vClickOutside'; // If imported locally
const showDropdown = ref(false);
const closeDropdown = () => {
showDropdown.value = false;
console.log('Dropdown closed by click outside!');
};
</script>
<style>
.dropdown-content {
border: 1px solid #ccc;
padding: 15px;
background-color: white;
position: absolute;
margin-top: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
border-radius: 4px;
}
</style>
How it works: This snippet provides a custom Vue 3 directive, `v-click-outside`, that executes a specified method when a click occurs outside the element to which the directive is bound. In `beforeMount`, it attaches a global click event listener to the document. This listener checks if the clicked target is neither the element itself nor a descendant of the element. If it's an outside click, the function passed to the directive (via `binding.value`) is invoked. In `unmounted`, the event listener is properly removed to prevent memory leaks. This directive is highly useful for common UI patterns like closing dropdowns, popovers, or side navigation menus when the user clicks elsewhere on the page.