Skip to content

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.

vue
<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, in v-my-directive="1 + 1", value is 2.
    • oldValue: The previous value, available only in beforeUpdate and updated.
    • arg: The argument passed to the directive (if any). For example, in v-my-directive:foo, arg's value is "foo".
    • modifiers: An object containing modifiers (if any). For example, in v-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 the beforeUpdate and updated hooks.

Example: Directive with Parameters

Let's create a directive that accepts a color value and sets the element's background color to that value.

vue
<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

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.

Content is for learning and research only.