Vue Tip: Creating a Custom Directive
In addition to the default set of directives like v-model
or v-show
, you can also register your own custom directives. For this article, let's look at how you can create a v-theme
directive that applies a specific style to an element of our template.
Info
Custom directives should be used for reusing logic that involves low-level DOM access on plain elements.
You can define the custom directive inside any Vue component:
1<template>
2 <span v-theme>Test</span>
3</template>
4
5<script setup>
6// enables v-theme in our template
7const vTheme = {
8 mounted: (el) => {
9 el.style.color = 'red'
10 },
11}
12</script>
We defined the custom directive as an object that contains the lifecycle hooks as a Vue component. The element the directive is bound to is available as the first argument of the lifecycle hooks.
In <script setup>
, any camelCase variable that starts with the v
prefix can be used as a custom directive.
Warning
Custom directives should only be used when the desired functionality can only be achieved via direct DOM manipulation. When possible, prefer declarative templating using built-in directives such as v-bind
because they are more efficient and server-rendering friendly.
Now let's extend our directive by adding an argument that defines which theme should be applied:
1<template>
2 <span v-theme:[theme]>Selected theme: {{ theme }}</span>
3 <button @click="switchTheme">Switch theme</button>
4</template>
5
6<script setup>
7import { ref } from 'vue'
8
9const theme = ref('primary')
10
11const switchTheme = () => {
12 if (theme.value === 'primary') {
13 theme.value = 'secondary'
14 } else if (theme.value === 'secondary') {
15 theme.value = 'primary'
16 }
17}
18
19const setThemeColor = (el, binding) => {
20 if (binding.arg === 'primary') {
21 el.style.color = 'orange'
22 } else if (binding.arg === 'secondary') {
23 el.style.color = 'green'
24 } else {
25 el.style.color = 'black'
26 }
27}
28
29// enables v-theme in our template
30const vTheme = {
31 mounted(el, binding) {
32 setThemeColor(el, binding)
33 },
34 updated(el, binding) {
35 setThemeColor(el, binding)
36 },
37}
38</script>
At this point, you have created a custom directive that you can use in your Vue.js application.
Check the official documentation for more information.
If you liked this Vue tip, follow me on X to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter:
Vue Tip: Avoid Directly DOM Manipulation
It is a no-go to manipulate the DOM in Vue.js directly. Instead, you should use the "ref" attribute.
Vue Tip: Test Vue Components Using Vue Testing Library
Vue Testing Library is my preferred Vue.js testing library that encourages good testing practices.