The hook functions for directives have been renamed to better align with the component lifecycle.
Additionally, the expression
string is no longer passed as part of the binding
object.
In Vue 2, custom directives were created by using the hooks listed below to target an element’s lifecycle, all of which are optional:
Here’s an example of this:
<p v-highlight="'yellow'">Highlight this text bright yellow</p>
Vue.directive('highlight', { bind(el, binding, vnode) { el.style.background = binding.value } })
Here, in the initial setup for this element, the directive binds a style by passing in a value, that can be updated to different values through the application.
In Vue 3, however, we’ve created a more cohesive API for custom directives. As you can see, they differ greatly from our component lifecycle methods even though we’re hooking into similar events. We’ve now unified them like so:
updated
, so this is redundant. Please use updated
instead.The final API is as follows:
const MyDirective = { created(el, binding, vnode, prevVnode) {}, // new beforeMount() {}, mounted() {}, beforeUpdate() {}, // new updated() {}, beforeUnmount() {}, // new unmounted() {} }
The resulting API could be used like this, mirroring the example from earlier:
<p v-highlight="'yellow'">Highlight this text bright yellow</p>
const app = Vue.createApp({}) app.directive('highlight', { beforeMount(el, binding, vnode) { el.style.background = binding.value } })
Now that the custom directive lifecycle hooks mirror those of the components themselves, they become easier to reason about and remember!
It's generally recommended to keep directives independent of the component instance they are used in. Accessing the instance from within a custom directive is often a sign that the directive should rather be a component itself. However, there are situations where this actually makes sense.
In Vue 2, the component instance had to be accessed through the vnode
argument:
bind(el, binding, vnode) { const vm = vnode.context }
In Vue 3, the instance is now part of the binding
:
mounted(el, binding, vnode) { const vm = binding.instance }
With fragments support, components can potentially have more than one root node. When applied to a multi-root component, a custom directive will be ignored and a warning will be logged.
© 2013–present Yuxi Evan You
Licensed under the MIT License.
https://v3.vuejs.org/guide/migration/custom-directives.html