Thursday, 30 March, 2017 UTC


Summary

When you talk about Vue.js, you usually talk about Components. Components, components, components. Components aren’t the only thing you can write with Vue though, and it’s a good thing too. What if you want to apply modifiers to your components? That’s where directives come in. Whether you knew it or not, you’ve been using them already. v-if, v-model, and v-for are all examples of directives. Today, we’re going to show you how to add an important directive that performs a critical task that we can’t live without. Setting the background of its element to a nice baby blue.
Creating a Directive
Let’s get right on into the thick of it then. Create a new file called AnnoyingBackgroundDirective.js.
Now, let’s write the directive. A directive is just an object with a few special functions on it.
AnnoyingBackgroundDirective.js
import Vue from 'vue'; const defaultBackgroundColor = '#86bbff' // Initialize the annoying-background directive. export const AnnoyingBackground { bind(el, binding, vnode) { // Allow users to customise the color by passing an expression. const color = binding.expression || defaultBackgroundColor // el might not be present for server-side rendering. if (el) { // Set the element's background color. el.style.backgroundColor = color } } } // You can also make it available globally. Vue.directive('annoying-background', AnnoyingBackground) 
Now to use it in a component, simply add it to your component template prefixed with a v-.
TotallyNormalComponent.vue
<template> <div> <p v-annoying-background>Baby blue looks good on me.</p> <p v-annoying-background="#0f0">I prefer neon green.</p> </div> </template> <script> import { AnnoyingBackground } from './AnnoyingBackgroundDirective.js'; export default { directives: { AnnoyingBackground } } </script> 
More Details
A directive has five possible hooks:
  • bind(element, binding, vnode) - Called when the directive is first bound to the component or element.
  • inserted(element, binding, vnode) - Called when the component or element is inserted into it’s parent node. It may not be in the DOM yet.
  • update(element, binding, vnode, oldVnode) - Called when the containing component has updated but potentially before its children do.
  • componentUpdated(element, binding, vnode, oldVnode) - Called when the containing component has updated but after its children do.
  • unbind(element, binding, vnode) - Called when the directive is unbound from the component or element.
The arguments are these:
  • element - The element the directive is bound to. May be undefined.
  • binding - (This is the fun one.) Contains any arguments, values, and modifiers passed to the directive.
    • binding.name - The name of the directive.
    • binding.value - The value of a JS expression passed to the directive, if any. (ie. v-directive="{cake: 'chocolate'}" -> binding.value.cake === 'chocolate')
    • binding.oldValue - The previous value of the directive, only provided in update and componentUpdated.
    • binding.expression - The value expression as a string: v-directive="{cake: 'chocolate'}" -> binding.expression === '{cake: 'chocolate'}'
    • binding.arg - The argument passed to the directive, if any. v-directive:myArg -> binding.arg === 'myArg'
    • binding.modifiers - An object containing any modifiers passed to the directive as booleans. v-directive.modifier.modifier2 -> JSON.stringify(binding.modifiers) === {"modifier": true, "modifier2": true}
  • vnode - This is a virtual node used by Vue’s renderer. Don’t touch this unless you know what you’re doing. :P
  • oldVnode - The previous version of the above vnode. Only available in the update hooks.
So yeah, directives are really simple to create, but you can do a lot of crazy stuff with them if you so wish. Here’s the documentation.

Bonus Round

  • Try creating a conditional directive! Hint: You’ll probably need to hook into the vNode API. Sorry.