0
0
VueHow-ToBeginner · 4 min read

How to Create v-click-outside Directive in Vue

Create a custom v-click-outside directive by adding event listeners to the document that detect clicks outside the bound element and trigger a callback. Use the directive's lifecycle hooks to add and remove these listeners properly.
📐

Syntax

The v-click-outside directive listens for clicks outside the element it is attached to and calls a specified method. It uses lifecycle hooks to add and remove event listeners on the document.

  • beforeMount: Adds the click event listener.
  • unmounted: Removes the event listener to avoid memory leaks.
  • handler: Checks if the click target is outside the element and calls the provided method.
javascript
const clickOutsideDirective = {
  beforeMount(el, binding) {
    el.clickOutsideEvent = event => {
      if (!(el === event.target || el.contains(event.target))) {
        binding.value(event);
      }
    };
    document.addEventListener('click', el.clickOutsideEvent);
  },
  unmounted(el) {
    document.removeEventListener('click', el.clickOutsideEvent);
  }
};
💻

Example

This example shows a Vue component using the v-click-outside directive to close a dropdown menu when clicking outside it.

vue
<template>
  <div>
    <button @click="open = !open">Toggle Dropdown</button>
    <div v-if="open" v-click-outside="closeDropdown" style="border: 1px solid #ccc; padding: 10px; width: 200px;">
      <p>This is a dropdown menu.</p>
      <p>Click outside to close it.</p>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue';

const clickOutsideDirective = {
  beforeMount(el, binding) {
    el.clickOutsideEvent = event => {
      if (!(el === event.target || el.contains(event.target))) {
        binding.value(event);
      }
    };
    document.addEventListener('click', el.clickOutsideEvent);
  },
  unmounted(el) {
    document.removeEventListener('click', el.clickOutsideEvent);
  }
};

export default {
  directives: {
    clickOutside: clickOutsideDirective
  },
  setup() {
    const open = ref(false);
    const closeDropdown = () => {
      open.value = false;
    };
    return { open, closeDropdown };
  }
};
</script>
Output
When you click the 'Toggle Dropdown' button, the dropdown menu appears. Clicking anywhere outside the dropdown closes it.
⚠️

Common Pitfalls

  • Not removing the event listener on unmount causes memory leaks.
  • Failing to check if the click is inside the element leads to unwanted triggers.
  • Binding the directive to a non-function value causes errors.

Always ensure the directive's value is a function and clean up listeners properly.

javascript
const wrongDirective = {
  beforeMount(el, binding) {
    // Missing check for inside clicks
    el.clickOutsideEvent = () => {
      binding.value();
    };
    document.addEventListener('click', el.clickOutsideEvent);
  },
  unmounted(el) {
    document.removeEventListener('click', el.clickOutsideEvent);
  }
};

// Corrected version uses event check and removes listener as shown in the Syntax section.
📊

Quick Reference

v-click-outside directive cheat sheet:

  • beforeMount: Add document click listener.
  • unmounted: Remove document click listener.
  • handler: Call method only if click is outside element.
  • binding.value: Must be a function to execute on outside click.

Key Takeaways

Use document click listeners in the directive to detect outside clicks.
Always remove event listeners in the unmounted hook to prevent memory leaks.
Check if the click target is outside the element before calling the handler.
The directive's value must be a function to handle the outside click event.
Register the directive in your component or globally to use v-click-outside.