Vue3 Custom Directives
In addition to the core directives (v-model and v-show) that come with default settings, Vue also allows for the registration of custom directives.
Below, we register a global directive v-focus, which has the function of automatically focusing an element when the page loads:
Example
<div id="app">
<p>When the page loads, the input element automatically gets focus:</p>
<input v-focus>
</div>
<script>
const app = Vue.createApp({})
// Register a global custom directive `v-focus`
app.directive('focus', {
// When the bound element is mounted into the DOM...
mounted(el) {
// Focus the element
el.focus()
}
})
app.mount('#app')
</script>
We can also register local directives using the directives option within an instance, which makes the directive available only within that instance:
Example
<div id="app">
<p>When the page loads, the input element automatically gets focus:</p>
<input v-focus>
</div>
<script>
const app = {
data() {
return {
}
},
directives: {
focus: {
// Directive definition
mounted(el) {
el.focus()
}
}
}
}
Vue.createApp(app).mount('#app')
</script>
Hooks
Hook Functions
The directive definition function provides several hook functions (optional):
created
: Called before the binding 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 binding element's parent component is mounted.beforeUpdate
: Called before the VNode of the containing component is updated.updated
: Called after the VNode of the containing component and its children VNodes are updated.beforeUnmount
: Called once before the directive is unbound from the element's parent component.unmounted
: Called once when the directive is unbound from the element and the parent component is unmounted.
Example
import { createApp } from 'vue'
const app = createApp({})
// Register
app.directive('my-directive', {
// The directive has a set of lifecycle hooks:
created() {},
beforeMount() {},
mounted() {},
beforeUpdate() {},
updated() {},
beforeUnmount() {},
unmounted() {}
})
// Register (functional directive)
app.directive('my-directive', () => {
// This will be called as both `mounted` and `updated`
})
// Getter, returns the directive definition if registered
const myDirective = app.directive('my-directive')
Hook Function Parameters
The hook functions receive the following parameters:
el
el
is the element to which the directive is bound. This can be used to directly manipulate the DOM.
binding
binding
is an object containing the following properties:
instance
: The instance of the component using the directive.value
: The value passed to the directive. For example, inv-my-directive="1 + 1"
, the value is2
.oldValue
: The previous value, only available inbeforeUpdate
andupdated
. Whether the value has changed or not is available.arg
: The argument passed to the directive (if any). For example, inv-my-directive:foo
, the arg is"foo"
.modifiers
: An object containing modifiers (if any). For example, inv-my-directive.foo.bar
, the modifiers object is{foo: true, bar: true}
.dir
: An object passed as an argument when registering the directive. For example, in the following directive:app.directive('focus', { mounted(el) { el.focus() } })
dir
will be the following object:
{
mounted(el) {
el.focus()
}
}
vnode
A blueprint of the real DOM element received as the el
parameter.
prevNode
The previous virtual node, only available in beforeUpdate
and updated
hooks.
The following example demonstrates the use of these parameters:
Example
<div id="app">
<div v-tutorialpro="{ name: 'tutorialpro.org', url: 'www.tutorialpro.org' }"></div>
</div>
<script>
const app = Vue.createApp({})
app.directive('tutorialpro', (el, binding, vnode) => {
console.log(binding.value.name) // => "tutorialpro.org"
console.log(binding.value.url) // => "www.tutorialpro.org"
var s = JSON.stringify
el.innerHTML = s(binding.value)
})
app.mount('#app')
</script>
Sometimes we don't need other hook functions, and we can use a shorthand function in the following format:
Vue.directive('tutorialpro', function (el, binding) {
// Set the background color of the directive
el.style.backgroundColor = binding.value.color
})
The directive function can accept all valid JavaScript expressions. The following example passes a JavaScript object:
Example
<div id="app">
<div v-tutorialpro="{ color: 'green', text: 'tutorialpro.org!' }"></div>
</div>
<script>
Vue.directive('tutorialpro', function (el, binding) {
// Shorthand to set text and background color
el.innerHTML = binding.value.text
el.style.backgroundColor = binding.value.color
})
new Vue({
el: '#app'
})
</script>