Vue Tip: Creating a Custom Directive
Michael Hoffmann
@mokkapps
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.
You can define the custom directive inside any Vue component:
<template>
<span v-theme>Test</span>
</template>
<script setup>
// enables v-theme in our template
const vTheme = {
mounted: (el) => {
el.style.color = 'red'
},
}
</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.
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:
<template>
<span v-theme:[theme]>Selected theme: {{ theme }}</span>
<button @click="switchTheme">Switch theme</button>
</template>
<script setup>
import { ref } from 'vue'
const theme = ref('primary')
const switchTheme = () => {
if (theme.value === 'primary') {
theme.value = 'secondary'
} else if (theme.value === 'secondary') {
theme.value = 'primary'
}
}
const setThemeColor = (el, binding) => {
if (binding.arg === 'primary') {
el.style.color = 'orange'
} else if (binding.arg === 'secondary') {
el.style.color = 'green'
} else {
el.style.color = 'black'
}
}
// enables v-theme in our template
const vTheme = {
mounted(el, binding) {
setThemeColor(el, binding)
},
updated(el, binding) {
setThemeColor(el, binding)
},
}
</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 BlueSky to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter :