AcademyVue
Custom Directives
A directive is the same mounted/unmounted lifecycle a component has, applied to a raw DOM element instead of a component instance.
2 min readUpdated 3 exercises
A directive is an object of DOM-element lifecycle hooks
const vFocus = {
mounted(el) {
el.focus()
},
}v-focus on any element calls this object's mounted(el) the moment that specific DOM element is inserted — el is the raw element, not a component instance, which is exactly the difference between a directive and a component: a directive attaches behavior to any element directly, with no template, no props, no render function of its own.
binding.value is whatever expression followed the =
<div v-my-directive="someExpression"></div>const vMyDirective = {
mounted(el, binding) {
console.log(binding.value) // whatever someExpression evaluated to
},
}A directive with an argument (v-my-directive:arg="value") and modifiers (v-my-directive.mod="value") exposes those on binding too (binding.arg, binding.modifiers.mod) — the same three-part shape (name:argument.modifier) every built-in directive uses.
The most common real directive: v-click-outside
const vClickOutside = {
mounted(el, binding) {
el.__handler__ = (event) => {
if (!el.contains(event.target)) binding.value()
}
document.addEventListener('click', el.__handler__)
},
unmounted(el) {
document.removeEventListener('click', el.__handler__)
},
}el.contains(event.target) is the actual check — a click is "outside" exactly when the clicked node is not a descendant of el. The listener lives on document, not on el itself, because a click has to be observed no matter where on the page it lands; storing the handler function on the element (el.__handler__) is what lets unmounted remove the exact same reference mounted added, the identical requirement onUnmounted's cleanup has for a component-level listener.
A directive with no mounted hook is a directive that does nothing
const vClickOutside = {} // valid object, zero hooks, zero behaviorThis compiles and applies to an element with no error — Vue does not require a directive to implement any specific hook. The mistake is invisible exactly because nothing crashes; the element you attached the directive to simply behaves as if the directive were never written.
What interviewers check
Whether you can build v-click-outside or v-focus live, from the hook names up — the two directives asked for most, and both are short enough to write from memory once the mounted/unmounted shape is genuinely understood rather than memorized.
Now practice it
2 quizzes · 1 drillReading this page is the cheap half. These are the exercises that make you use it.
- Custom DirectivesProAn empty v-click-outside directive object — build the mounted/unmounted hooks this page walks through from scratch.DrillSolve · MediumDrillSolve · Medium
- Performance · shallowRef & markRawDirectives that touch the DOM directly (shallowRef, markRaw territory) are exactly where this set's questions live.QuizTake · MediumQuizTake · Medium
- Options API · Vue ExpertProDirective internals sit at the deep end of the Vue Fundamentals series — this set is the way to meet them.QuizTake · HardQuizTake · Hard
Read next
Lifecycle Hooks
Every lifecycle hook that sets something up has a matching one that tears it down — onMounted without onUnmounted is a leak waiting to happen.
2 min
Template Refs: Reaching the Real DOM
A template ref is null until onMounted — the component has to exist in the DOM before anything can point at it.
2 min