Getting Started With Vue.js: Directives
Tags: vue
Published: 2020-12-16 01:46:00

Continuing on from my last two blog posts, I’ll be talking more about some of the basics of Vue.js. I have covered how to start a project using Vue and some of the ways you can use the Vue instance in a project. In this post, I’ll go over Vue’s *directives*; the way to make your webpages interactive with the data in your Vue instances.

Directives are special attributes provided by Vue. They are prefixed with `v-` and each one applies specific reactive behavior to the HTML element you add it to on the page. The main Vue directives are `v-bind`, `v-if`, `v-for`, and `v-on`. An example using `v-bind` looks like this:
```
<div v-bind:id="someVariable"></div>
```
The `v-bind` attribute is used to access Vue instance variables from inside an HTML attribute. The example above shows the `v-bind` attribute being used to assign the *id* of the *div* to a variable called `someVariable`. Unlike referencing a variable in between HTML elements, you cannot use double curly braces to interpret variables in HTML attributes, you have to use `v-bind` instead:
```
<!-- Doesn't work, causes an error! -->
<a href={{ url }}>Vue.js</a>
<!-- This is the correct way to assign the href attribute to url -->
<a v-bind:href="url">Vue.js</a>
```
You can use `v-bind` to assign any attribute an element might have to a variable. But `v-bind` can get more confusing when you need to attach more than one variable to an attribute. When adding styling to a page, the *class* and *style* attributes might need to have many variables associated with them. In that case, you can use array or object syntax with `v-bind`, like these examples with multiple classes on each element:
```
<div v-bind:class="[activeClass, errorClass]">
  <!-- This will have the class names of whatever is in
    the 'activeClass' and 'errorClass' variables -->
</div>
<div v-bind:class="{ active: isActive, 'text-danger': hasError }" >
  <!-- This will have the classes of 'active' and 'text-danger'
    depending on if their variables are true or false -->
</div>
```
When using the style attribute, it’s often better to create a style object in the instance to bind to the attribute:
```
// in index.html
<div v-bind:style="styleObject">
  <!-- content -->
</div>
// in index.js
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}
```
This way, if your style object gets too big, it’s not taking up space in your HTML.

The next directive uses a concept that should be very familiar to any programmer. The `v-if` directive is used for conditional rendering, and it evaluates the condition it is given the same way as an if-statement does in code. For example:
```
<div id="if-directive">
  <h1 v-if="condition">I'm conditionally rendered!</h1>
</div>
```
In this example, the `condition` that `v-if` points to should be some data that you have defined that can be evaluated to *true* or *false*. Now, if the `condition` is *true*, you will see the `h1` tag on the webpage, and if it is *false*, this will be an empty `div`. You can test this out by creating a Vue instance attached to this `div`:
```
let ifDirective = new Vue({
  el: "#if-directive",
  data: {
    condition: true
  }
})
```
Now, if you have the page open in your browser, you should see the `h1` tag, but if you open the console and set `ifDirective.condition` to *false*, you can see the header disappear.

Just like if-statements with any programming language, `v-if` also has the associated `v-else` and `v-else-if` so you can give other options for what to render depending on a variety if conditions, like this:
```
<div id="gender">
  <p v-if="person.gender === 'M'">
    Male
  </p>
  <p v-else-if="person.gender === 'F'">
    Female
  </p>
  <p v-else>
    Other
  </p>
</div>
```
And the last directive I’ll talk about in this post is `v-for`. This should also sound familiar to any programmer, and as you might expect, the `v-for` attribute is designed to loop over a collection or list. Here’s an example of what a Vue instance with a list could look like:
```
const forDirective = new Vue({
  el: "#for-directive",
  data: {
    todos: [
      { text: 'Wash dishes', isComplete: false },
      { text: 'Do laundry', isComplete: true },
      { text: 'Check email', isComplete: false }
    ]
  }
})
```
And the HTML would look like this:
```
<ul id="for-directive">
  <li v-for="todo in todos">
    {{ todo.text }}
  </li>
</ul>
```
![Todo List](https://dev-to-uploads.s3.amazonaws.com/i/jvh0cubauaerj1d98ufn.png) This will render a list like the one above. If you have the *index.html* page open in your browser and you open the console, you can add or remove items in the `todos` array and see the list update on the page. The list will always update whenever there is a change to the list in your instance. The `v-for` attribute also gives you the ability to loop over an object, and a way to access the index and/or key of each of the elements in the collection:
```
// Using the index of each item in the array
v-for="(item, index) in items"
// Looping over an object
v-for="value in object"
// Looping over an object with it's key names and index values
v-for="(value, name, index) in object"
```
One thing to note is that it is not advised to use `v-if` with `v-for`. The main reason to try to use them together is when you only want to display items in the list that fit a condition. But the better way to do this is to use a computed property. You should use computed properties to display a sorted or filtered part of your original list. If we use the example from earlier with the todo list, we could add a computed property to the instance that filters the list by items that are not completed, like so:
```
computed: {
  completedTodos: function () {
    return this.todos.filter(function (todo) {
      return !todo.isComplete
    })
  }
}
```
Then you can use `v-for` with this computed property to only display the todos that are not completed to the page:
```
<li v-for="todo in completedTodos">
  {{ todo.text }}
</li>
```
Another thing to note about the `v-for` directive is that you should give each element in the list a unique key attribute. This is so that Vue can properly keep track of each element’s identity so it will reuse existing elements, instead of recreating them when there is a change to the collection:
```
<div v-for="item in items" v-bind:key="item.id">
  <!-- content -->
</div>
```
Now, with everything I have talked about in my blog posts on Vue, I have covered most of the different ways to display data from your Vue instances to a webpage. And because of the the way Vue is set up, the page will change according to any updates that are made to the data. But I still haven’t really covered how to allow a user to interact with your webpage. That requires the use of the `v-on` directive, and I’ll spend time talking about that in my next blog post.