In addition to the built-in directives, Vue.js allows us to create our own custom directives.
Generally, this is not something we need to do frequently. Vue is designed to manipulate the DOM using its own mechanisms.
However, it can sometimes 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.
Creating a Custom Directive
Creating a custom directive in Vue is very simple. It is just an object that contains hooks that are executed at different times in the lifecycle of the elements.
The most common hooks for creating custom directives are:
- mounted: Executes when the element is inserted into the DOM.
- updated: Executes when the element is updated.
- unmounted: Executes 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 look at this 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 directive
v-highlight
adds a click event to the element that changes its background color. - Additionally, it 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 the standard mechanisms of Vue.js. 😊
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 specific to the DOM: 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 is better to avoid a directive - The logic is complex: Directives are harder to debug and maintain
Same Example Without a Directive
To see it, let’s look at the same example of v-highlight
but without a directive, using Vue’s reactive tools. It would look 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-bind
andv-on
, which are basic tools of Vue - You do not need to manipulate the DOM manually
- The logic is in the state (
isHighlighted
) and not in a directive - Easier to create, debug, and extend