In addition to the built-in directives, Vue.js allows us to create our own custom directives.
In general, this is not something we need to do frequently. Vue is designed to manipulate the DOM using its own mechanisms.
But sometimes it can be useful, when we need to manipulate the DOM in a specific way that is not covered by the standard directives.
So let’s see how to create our own directives and, above all, when it is appropriate (and when it is not) to do so.
Create a Custom Directive
Creating a custom directive in Vue is very simple. It is simply an object containing hooks that are executed at different moments in the element’s lifecycle.
The most common hooks for creating custom directives are:
- mounted: Executed when the element is inserted into the DOM.
- updated: Executed when the element is updated.
- unmounted: Executed when the element is removed from the DOM.
We saw the hooks and the component lifecycle in Component Lifecycle in Vue.js
Basic Example
Let’s see it better with an example. Suppose we want to create a custom directive called v-highlight, which changes the background color of an element when it is clicked.
<template>
<p v-highlight>Click here to highlight</p>
</template>
<script setup>
import { ref } from 'vue';
const vHighlight = {
mounted(el) {
el.style.cursor = 'pointer';
el.addEventListener('click', () => {
el.style.backgroundColor = 'yellow';
});
},
unmounted(el) {
el.removeEventListener('click', () => {});
}
};
</script>
In this example,
- The
v-highlightdirective adds a click event to the element that changes its background color. - It also cleans up the event when the element is removed from the DOM.
When to Use a Directive
In general, it is preferable not to create our own directives if we can solve it with Vue.js’s standard mechanisms. 😊
We should reserve it for complex cases, or cases where you need to reuse the logic (for example, in component libraries or tools).
Directives are suitable when,
- You need to manipulate the DOM directly: For example, adding events, modifying styles, or interacting with external libraries
- You want to reuse the logic in multiple components
- The logic is DOM-specific: If you are working with HTML elements (and not with the application state)
Directives are not suitable when,
- The logic can be handled with Vue’s reactive system: If you can achieve the same with
v-bind,v-on, or dynamic classes, it’s better to avoid a directive - The logic is complex: Directives are harder to debug and maintain
Same Example Without a Directive
To illustrate, let’s look at the same v-highlight example but without a directive, using Vue’s reactive tools. It would look something like this,
<template>
<p
:class="{ highlighted: isHighlighted }"
@click="toggleHighlight"
style="cursor: pointer;"
>
Click here to highlight
</p>
</template>
<script setup>
import { ref } from 'vue';
const isHighlighted = ref(false);
function toggleHighlight() {
isHighlighted.value = !isHighlighted.value;
}
</script>
<style>
.highlighted {
background-color: yellow;
transition: background-color 0.3s;
}
</style>
Advantages of This Alternative
- Uses
v-bindandv-on, which are basic Vue tools - You don’t need to manipulate the DOM manually
- The logic is in the state (
isHighlighted) and not in a directive - Easier to create, debug, and extend
