JAVASCRIPT
Vue 3 Custom Directive for Debounced Clicks
Create a reusable Vue 3 custom directive, `v-debounce-click`, to prevent rapid multiple clicks on a button or element, enhancing user interface stability.
<!-- main.js (or plugin file) -->
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.directive('debounce-click', {
mounted(el, binding) {
let timer;
const delay = parseInt(binding.arg || '500'); // Default 500ms delay
const clickHandler = () => {
clearTimeout(timer);
timer = setTimeout(() => {
if (binding.value && typeof binding.value === 'function') {
binding.value();
}
}, delay);
};
el.addEventListener('click', clickHandler);
el._debounceClickHandler = clickHandler; // Store for unmounted hook
},
unmounted(el) {
if (el._debounceClickHandler) {
el.removeEventListener('click', el._debounceClickHandler);
delete el._debounceClickHandler;
}
}
});
app.mount('#app');
// App.vue
<template>
<div>
<h1>Custom Directive Demo</h1>
<button v-debounce-click="handleClick">Click me (500ms debounce)</button>
<button v-debounce-click:1000="handleAnotherClick">Click me (1000ms debounce)</button>
<p>Clicks: {{ count }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
const handleClick = () => {
count.value++;
console.log('Button clicked!', count.value);
};
const handleAnotherClick = () => {
count.value++;
console.log('Another button clicked!', count.value);
};
</script>
How it works: Custom directives in Vue 3 allow developers to encapsulate reusable DOM manipulation logic. This snippet demonstrates `v-debounce-click`, a directive that prevents a click event handler from firing too rapidly. When applied to an element, it delays the execution of the bound function until a specified `delay` has passed without another click. The `mounted` hook sets up the event listener with a debounce mechanism, and the `unmounted` hook ensures proper cleanup by removing the event listener to prevent memory leaks. The delay can be customized using a directive argument (e.g., `v-debounce-click:1000`).