π¨ Vue.js Custom Directives: Teaching Your App New Tricks!
The Magic Wand Analogy πͺ
Imagine you have a magic wand. Every time you wave it at something, that thing does exactly what you tell it to do. Custom directives in Vue.js are just like that magic wand!
When you point your wand (directive) at an element, you give it special powers that Vue doesnβt have built-in.
What Are Custom Directives?
Think about when you learned to ride a bicycle. Someone taught you how to balance, pedal, and steer. Custom directives teach HTML elements new behaviors!
Built-in vs Custom
Vue already has some magic wands:
v-ifβ Makes things appear/disappearv-forβ Creates copies of thingsv-modelβ Connects form inputs to data
But what if you need your own special power?
// Creating your own magic wand!
const vFocus = {
mounted(el) {
el.focus()
}
}
What happened?
- We created a wand called
vFocus - When an element appears, it automatically gets focus!
Using Your Magic Wand
<input v-focus />
Thatβs it! The input box will automatically be ready to type in when the page loads. No clicking needed!
π Directive Hooks: When Does the Magic Happen?
Just like a day has morning, afternoon, and night, an element has different moments in its life. Hooks let you do magic at the perfect moment!
The Elementβs Life Story
graph TD A["π± Created"] --> B["π Mounted"] B --> C["π Updated"] C --> D["π« Unmounted"]
All The Hooks Explained
| Hook | When It Happens | Real Life Example |
|---|---|---|
created |
Element is born | Baby is born |
beforeMount |
About to appear | Getting ready for school |
mounted |
Now visible! | Arrived at school |
beforeUpdate |
Data will change | About to change clothes |
updated |
Data changed | Wearing new clothes |
beforeUnmount |
About to leave | Packing bags to go |
unmounted |
Gone! | Left the building |
Example: Greeting at Every Stage
const vLifecycle = {
created() {
console.log("π± I'm born!")
},
mounted(el) {
console.log("π I can be seen!")
el.style.color = 'green'
},
updated() {
console.log("π Something changed!")
},
unmounted() {
console.log("π Goodbye!")
}
}
π Directive Hook Arguments: The Magic Ingredients
When you wave your magic wand, you need ingredients to make it work. These arguments are the ingredients!
The Four Magic Ingredients
Every hook receives these helpful friends:
graph LR A["πͺ Hook Called"] --> B["el: The Element"] A --> C["binding: The Instructions"] A --> D[vnode: Vue's Blueprint] A --> E["prevVnode: Old Blueprint"]
1. el - The Element Itself
This is the actual HTML element youβre pointing at.
const vColor = {
mounted(el) {
// el IS the element!
el.style.backgroundColor = 'yellow'
}
}
2. binding - The Instructions
This object tells you WHAT the user wants:
const vColor = {
mounted(el, binding) {
// binding.value = what user passed
el.style.color = binding.value
}
}
<p v-color="'red'">I'm red!</p>
<p v-color="'blue'">I'm blue!</p>
Inside the binding Object
| Property | What It Means | Example |
|---|---|---|
value |
Current value | 'red' |
oldValue |
Previous value | 'blue' |
arg |
After the colon | v-color:bg β 'bg' |
modifiers |
After dots | v-color.bold β {bold: true} |
instance |
Component using it | The Vue component |
dir |
The directive object | The whole directive |
Complete Example with All Parts
const vHighlight = {
mounted(el, binding) {
// binding.value = the color
// binding.arg = where to apply
// binding.modifiers = extra options
const color = binding.value || 'yellow'
const target = binding.arg || 'background'
if (target === 'background') {
el.style.backgroundColor = color
} else {
el.style.color = color
}
if (binding.modifiers.bold) {
el.style.fontWeight = 'bold'
}
}
}
<!-- Yellow background -->
<p v-highlight>Hello!</p>
<!-- Red text -->
<p v-highlight:text="'red'">Red text!</p>
<!-- Blue background, bold -->
<p v-highlight.bold="'blue'">Bold blue!</p>
3. vnode - Vueβs Blueprint
This is Vueβs internal representation. You rarely need it, but itβs there!
mounted(el, binding, vnode) {
console.log(vnode.type) // Element type
}
4. prevVnode - The Old Blueprint
Only available in updated and beforeUpdate. Shows what it looked like before.
updated(el, binding, vnode, prevVnode) {
console.log('Changed from:', prevVnode)
console.log('Changed to:', vnode)
}
π Registering Your Directives
Local Registration (One Component)
export default {
directives: {
focus: vFocus,
color: vColor
}
}
Global Registration (Everywhere!)
const app = createApp(App)
app.directive('focus', vFocus)
app.directive('color', vColor)
app.mount('#app')
π― Real-World Example: Auto-Resize Textarea
Letβs build something useful! A textarea that grows as you type.
const vAutoResize = {
mounted(el) {
el.style.overflow = 'hidden'
el.style.resize = 'none'
const resize = () => {
el.style.height = 'auto'
el.style.height = el.scrollHeight + 'px'
}
el.addEventListener('input', resize)
resize() // Initial resize
}
}
<textarea v-auto-resize>
Type here and watch me grow!
</textarea>
π‘ Quick Summary
| Concept | What It Does |
|---|---|
| Custom Directive | Teaches elements new tricks |
| Hooks | When the magic happens |
| el | The element to modify |
| binding | What the user wants |
| value | The passed data |
| arg | Extra instruction after : |
| modifiers | Options after . |
π You Did It!
You now know how to:
- β Create your own custom directives
- β Use hooks to control timing
- β Access all the magic ingredients
- β Build real, useful features
Custom directives are your secret superpower. Use them to make your Vue apps do exactly what you imagine! π
