Custom Directives
In addition to Vue's built-in series of directives (such as v-model or v-show), Vue also allows you to register your own custom directives. The main application scenarios for custom directives are to perform low-level operations on ordinary DOM elements.
A common example is to make a certain input box automatically receive focus when the page loads. Although this can be implemented manually through ref, using a custom directive can better encapsulate and reuse this behavior.
Creating a Custom Directive
In <script setup>, any camelCase-named variable starting with v can be used as a custom directive. In the following example, the vFocus directive can be used in the template as v-focus.
<script setup>
// Enable v-focus in the template
const vFocus = {
// When the bound element is mounted into the DOM...
mounted: (el) => {
// Focus the element
el.focus()
}
}
</script>
<template>
<input v-focus />
</template>Directive Lifecycle Hooks
A directive definition object can provide the following hook functions (all optional):
created: Called before the bound element's attributes or event listeners are applied.beforeMount: Called when the directive is first bound to the element and before the parent component is mounted.mounted: Called after the bound element's parent component is mounted.beforeUpdate: Called before updating the VNode of the component that contains the binding.updated: Called after the VNode of the component containing the binding and the VNodes of its child components are updated.beforeUnmount: Called before the parent component of the bound element is unmounted.unmounted: Called when the directive is unbound from the element and the parent component is unmounted.
Hook Function Parameters
Directive hooks are passed the following parameters:
el: The element to which the directive is bound, which can be used to directly manipulate the DOM.binding: An object containing the following properties:value: The directive's binding value. For example, inv-my-directive="1 + 1",valueis2.oldValue: The previous value, available only inbeforeUpdateandupdated.arg: The argument passed to the directive (if any). For example, inv-my-directive:foo,arg's value is"foo".modifiers: An object containing modifiers (if any). For example, inv-my-directive.foo.bar,modifiers's value is{ foo: true, bar: true }.
vnode: Represents the underlying VNode of the bound element.prevVnode: Represents the VNode of the element to which the directive was bound in the previous render. Available only in thebeforeUpdateandupdatedhooks.
Example: Directive with Parameters
Let's create a directive that accepts a color value and sets the element's background color to that value.
<script setup>
const vBackgroundColor = {
mounted: (el, binding) => {
// binding.value is the value passed to the directive
el.style.backgroundColor = binding.value
}
}
</script>
<template>
<div v-background-color="'red'">This will have a red background.</div>
<p v-background-color="'#cba'">And this one, a light purple.</p>
</template>Globally Registering Directives
If you want to use a certain directive in any component of the application, you can globally register it in main.js.
main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Register a global custom directive `v-focus`
app.directive('focus', {
mounted: (el) => {
el.focus()
}
})
app.mount('#app')Custom directives provide a powerful way to encapsulate reusable DOM operations, allowing our component logic to focus more on data and business logic rather than low-level DOM details.