DEV Community

Cover image for Vue.js: Mastering V-Directives, Creating Custom Directives with Examples
WebCraft Notes
WebCraft Notes

Posted on • Edited on • Originally published at webcraft-notes.com

Vue.js: Mastering V-Directives, Creating Custom Directives with Examples

Also, please check this post in my web notes

Every framework has its built-in functionality that makes that framework something special, the same staff is with Vue.js. In this article, we will talk about directives and the way they can simplify development. In Vue.js, directives are special attributes that allow you to apply reactive behavior to the DOM (Document Object Model) when rendering the view. They are prefixed with the "v-" notation. Directives are used to manipulate elements, modify their behavior, or dynamically update their content based on data changes.
In the first part of the article, we will talk about the main built-in directives, and in the second part, we will build a custom directive with its functionality.

Part 1: Built-in directives.

  • v-bind. This directive allows us to bind dynamically one or more attributes, or a component prop to an expression. In other words, if we want to update any tag attribute dynamically or share some data with a child component we need to use the v-bind directive. Usually, we use ":" as shorthand.
<template>
  <main>
    <img v-bind:src="imageSrc" alt="Vue logo">
  </main>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      imageSrc: 'https://vuejs.org/images/logo.png'
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

In this example we set the image src attribute "imageSrc" variable so now we can update "imageSrc" value with the valid route and the image will be updated dynamically in our app.

  • v-if, v-else, v-else-if. We can not spend time thinking about the strategy of displaying or not displaying elements, writing unnecessary functions that will contain conditions, and puzzling over how to add them to our template. That's because we have "v-if, v-else, v-else-if" directives. These directives conditionally render an element or a template fragment based on the truthfulness of the expression value. When a v-if element is toggled, the element and its contained directives/components are destroyed and re-constructed. If the initial condition is false, then the inner content won't be rendered at all. Let's check an example and it will be easier to configure the logic:
<template>
  <main>
    <div>
      <h1 v-if="planet === 'Earth'">Hello Earth!</h1>
      <h1 v-else-if="planet === 'Mars'">Hello Mars!</h1>
      <h1 v-else="planet === 'Venus'">Hello Venus!</h1>
    </div>
  </main>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      planet: "Mars",
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

We can rewrite v-if directives with a conditional statement:

<template>
  <main>
    <div>
      <h1>{{ message }}</h1>
    </div>
  </main>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      planet: "Mars",
      message: "",
    }
  },
  methods: {
    findMessage() {
      if (planet === "Earth") {
        this.message = "Hello Earth!";
      } else if (planet === "Mars") {
        this.message = "Hello Mars!";
      } else {
        this.message = "Hello World!";
      }
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

That's it, easy to use but "a whole world of possibilities". Let's go on!

  • v-show. Toggle the element's visibility based on the truthfulness of the expression value. Sounds similar to the v-if directive but not exactly. The v-if directive renders or destroys an element outside the DOM depending on the condition. v-show directive setting the display CSS property via inline styles. It means that if the v-show condition returns false then the element display value will be "none". Here is an example:
<template>
  <main>
    <div>
      <h1 v-show="planet === 'Mars'">Hello Mars!</h1>
    </div>
  </main>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      planet: "Mars"
    }
  },
}
</script>
Enter fullscreen mode Exit fullscreen mode
  • v-for. If you need to render the element multiple times or render a list for example then you need this directive. Let's check the syntax in a small example:
<template>
  <main>
    <ul>
      <li v-for="(planet, index) in planets" :key="index">{{ planet }}</li>
    </ul>
  </main>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      planets: ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"],
    }
  },
}
</script>
Enter fullscreen mode Exit fullscreen mode

Okay, we use the v-for directive where define each element as "planet" in an array of "planets", also we added an index because it will be necessary for the key attribute to have a unique value. The "key" attribute helps Vue.js to efficiently update and re-render the elements in the list. The result will be a list of planets on our webpage.

  • v-model. The "v-model" directive in Vue.js is a two-way binding directive that allows you to create a connection between the data in your Vue instance and an input element, such as an input field, checkbox, or select dropdown. By using "v-model," you can bind the value of the input element to a data property in your Vue instance. This means that changes in the input element will update the data property, and changes to the data property will update the input element. Let's bind the input value and variable in a simple example:
<template>
  <main>
    <input type="text" v-model="planet"/>
  </main>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      planet: "Earth",
    }
  },
}
</script>
Enter fullscreen mode Exit fullscreen mode
  • v-on. The v-on directive in Vue.js is used to listen to specific events on an element and trigger a method or expression when that event occurs. It allows you to add event listeners to your HTML elements and bind them to methods or expressions in your Vue instance. Sign "@" is a shorthand for v-on listeners. Let's check a simple example of what we just wrote:
<template>
  <main>
    <button @click="sayHello('Earth')">Say Hello</button>
  </main>
</template>

<script>
export default {
  name: "App",
  methods: {
    sayHello(planet) {
      console.log(`Hello from ${planet}`)
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

There are much more useful directives like v-text, v-html, v-memo... about which, I hope, we can talk later. But let's work a little bit on the second part of our post and create our v-directive.

Part 2: Create Custom Directive

If we want to create a custom v-directive we need to use a Vue.directive() method. Vue.directive() takes an object as the second argument, which contains several lifecycle hooks for the directive:

  • created - new! This is called before the element's attributes or event listeners are applied.
  • bind → beforeMount
  • inserted → mounted
  • beforeUpdate: new! This is called before the element itself is updated, much like the component lifecycle hooks.
  • update → removed! There were too many similarities to updated, so this is redundant. Please use updated instead.
  • componentUpdated → updated
  • beforeUnmount: new! Similar to component lifecycle hooks, this will be called right before an element is unmounted.
  • unbind -> unmounted Here is a small example:
const MyDirective = {
  created(el, binding, vnode, prevVnode) {}, // new
  beforeMount() {},
  mounted() {},
  beforeUpdate() {}, // new
  updated() {},
  beforeUnmount() {}, // new
  unmounted() {}
}
Enter fullscreen mode Exit fullscreen mode

These hooks allow you to perform actions at different stages of the directive's lifecycle. Once we have defined the custom directive, we can use it in your Vue components by adding the "v-directive" attribute to the desired element. It was a little bit of theory and now let's check the code part:
We will add v-directive into our main.js file and make it global. It will be a simple directive that will change...
Continue Reading...

Top comments (0)