VueJs is a small, flexible JavaScript library that allows developers to build interactive web applications quite easily through an API that is simple and easy to pick up. It shares some similarities and a number of differences with other libraries/frameworks like Angular, React, Ember, Polymer, and Riot to name a few. However Vue prides itself on it's simplicity, performance, flexibility and being less opinionated. The VueJs website has a more in depth comparison with other libraries and frameworks which you can read about here, if you're interested.

This tutorial aims to give you an overview of some of the basic concepts and features through practical examples. In future tutorials we'll be looking at more advanced features and building scalable applications with Vue.

Creating a Vue Instance with new Vue()

Let's start off by creating a basic HTML page and importing VueJs into it. You can install Vue via NPM, Bower, as a standalone, or a CDN, to name just a few ways. For the sake of simplicity, we'll stick to importing Vue via a CDN right before the closing body tag, like so:

<!DOCTYPE html>
<html>
  <head>
    <title>VueJs Tutorial - coligo</title>
  </head>
  <body>

  <script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
  </body>
</html>

Note: when developing, be sure to use the non-minified version as it provides you with helpful and descriptive warnings that will save you a lot of time.

We can now create a div tag and a new Vue instance then bind the two together. When you create a new Vue instance using the Vue() constructor, you need to specify it's mounting point which you can simply think of as a boundary or a box for this Vue instance - it will only know about the things that are declared within this boundary but nothing about what exists outside this div element.

You can specify the mounting point of a Vue instance using the el option in the Vue() constructor which takes a CSS selector string to the DOM element you wish to mount your Vue instance to like so:

<!DOCTYPE html>
<html>
  <head>
    <title>VueJs Tutorial - coligo</title>
  </head>
  <body>

  <div id="vue-instance">
    <!-- this will be the DOM element we will mount our VueJs instance to -->
  </div>

  <script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

  <script>
    // our VueJs instance bound to the div with an id of vue-instance
    var vm = new Vue({
      el: '#vue-instance'
    });
  </script>

  </body>
</html>

As you can see above, a Vue instance is created using the Vue() constructor and takes in an options object that specifies the element to mount on. In this case we are creating a new Vue instance and specifying the element to be mounted via the CSS selector: #vue-instance. A Vue instance can also be thought of as a ViewModel in the MVVM pattern, hence the variable name vm in case you were wondering.

Now that we have created a Vue instance and mounted it to a DOM element, Vue is aware of anything within those div tags and we can begin demonstrating some of the neat features of Vue.

2-Way Data Binding with v-model

To illustrate the 2-way data binding feature of Vue, we will create a simple HTML text input with the v-model directive that will be used to dynamically update the greeting property in the data object.

You can think of the v-model directive as any other HTML attribute. It creates 2-way data bindings on form input elements such as <input>, <textarea>, and <select>. The value of the v-model directive is the data we wish to update on user input events. For this particular example, we are binding the <input> element to the greeting string that we have created in the Vue data object as shown below:

...

<div id="vue-instance">
  <!-- this will be the DOM element we will mount our VueJs instance to -->
  Enter a greeting: <input type="text" v-model="greeting">
</div>

<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

<script>
  // our VueJs instance bound to the div with an id of vue-instance
  var vm = new Vue({
    el: '#vue-instance',
    data: {
      greeting: 'Hello VueJs!'
    }
  });
</script>

...

Now any time a user input event fires on the text box, the greeting string will be updated automatically and if the greeting string is changed, then the text box will also be automatically updated to reflect those changes. This constant synchronization between form input elements and underlying data is achieved using the v-model attribute and it is also where the 2-way data binding notion arises.

To prove this 2 way data binding between the <input> element and the underlying greeting string, we can dump the data object of this Vue instance to the page using the special $data property between double curly braces which essentially tells Vue to replace whatever is between those curly braces {{ }} with the property in the corresponding data object.

...

<div id="vue-instance">
  <!-- this will be the DOM element we will mount our VueJs instance to -->
  Enter a greeting: <input type="text" v-model="greeting">
    <pre>{{ $data | json }}</pre>
</div>

<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

<script>
  // our VueJs instance bound to the div with an id of vue-instance
  var vm = new Vue({
    el: '#vue-instance',
    data: {
      greeting: 'Hello VueJs!'
    }
  });
</script>

...

Go ahead and try it out here!

The | json in {{ $data | json }} is just a helper method (or a filter in Vue-terms) to pretty print the $data object. All it really does is call JSON.stringify() under the hood.

In a similar manner, you can display only the greeting string from the data object using the double curly braces like so:

...

<div id="vue-instance">
  <!-- this will be the DOM element we will mount our VueJs instance to -->
  Enter a greeting: <input type="text" v-model="greeting">
    <p>{{ greeting }}</p>
</div>

...

Vue makes this sort of data binding really easy as you can see. You don't need to write any input event handlers in pure Javascript or JQuery, all it took was a single v-model directive to bind the input element to underlying data. If we look at the code as a whole, we can really appreciate how much Vue abstracts away and simplifies event handling logic:

...
<body>

<div id="vue-instance">
    Enter a greeting: <input type="text" v-model="greeting">
    <p>{{ greeting }}</p>
</div>

<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

<script>
    var vm = new Vue({
        el: '#vue-instance',
        data: {
            greeting: 'Hello VueJs!'
        }
    });
</script>

</body>
...

Handling Events with v-on

VueJs makes listening to DOM events and assigning event handlers a breeze with the v-on directive. You can attach an event listener to an element by creating a method in the Vue instance and assigning it to the click handler.

In this case we created a method called sayHello in our methods object which displays a alert box with the name that the user has entered. The sayHello method is assigned as the click handler for the button using the v-on:click directive.

<div id="vue-instance">
  Enter your name: <input type="text" v-model="name">
  <button v-on:click="sayHello">Hey there!</button>
</div>

<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

<script>
  var vm = new Vue({
    el: '#vue-instance',
    data: {
      name: ''
    },
    methods: {
      sayHello: function(){
        alert('Hey there, ' + this.name);
      }
    }
  });
</script>

(you won't see an alert in the demo below if you have a popup/ad blocker enabled)

Of course you're not limited to just the click event as the v-on directive accepts the common Javascript events such as v-on:mouseover, v-on:keydown, v-on:submit, v-on:keypress, etc... or even your own custom defined events.

Since you will find yourself using the v-on:* directive quite frequently when developing, Vue provides us with a shorthand notation denoted by the @ symbol and you can simply replace this statement in our previous example:

<button v-on:click="sayHello">Hey there!</button>

with an equivalent @ version:

<button @click="sayHello">Hey there!</button>

Conditional Rendering with v-if and v-show

Let's say you wish to display a generic welcome message to your user if they are logged in or show them a login form if they are not already logged in. Vue makes this quite easy using the v-if and v-show directives, so let's take a look at how we can accomplish this.

Using what we learned in the previous section about handling events with the v-on directive, we will create a simple login method that toggles the value of isLoggedIn between true and false when the user clicks the login or logout button.

As the value of isLoggedIn changes, Vue will automatically re-evaluate the condition in the v-if directive and render the correct part of the content based on that condition.

...

<body>

<div id="vue-instance">
  <div v-if="isLoggedIn">
    Welcome to coligo!
    <button @click="login" type="submit">Logout</button>
  </div>
  <div v-else>
    <input type="text" placeholder="username">
    <input type="password" placeholder="password">
    <button @click="login" type="submit">Login</button>
  </div>
</div>

<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

<script>
  var vm = new Vue({
    el: '#vue-instance',
    data: {
      isLoggedIn: false
    },
    methods:{
      login: function(){
        // 'this' refers to the vm instance
        this.isLoggedIn = !this.isLoggedIn;
      }
    }
  });
</script>

</body>

...

v-show can be used in pretty much the same was as v-if and you can see that for yourself by replacing the v-if in the pervious example with a v-show like so:

<div id="vue-instance">
  <div v-show="isLoggedIn">
    Welcome to coligo!
    <button @click="login" type="submit">Logout</button>
  </div>
  <div v-else>
    <input type="text" placeholder="username">
    <input type="password" placeholder="password">
    <button @click="login" type="submit">Login</button>
  </div>
</div>

However, the difference is in the way they show and hide content:

v-show will always render the content regardless of the truthy-ness of the expression value whereas v-if will only render the content if the expression is true.

Also, each time the value of the expression toggles between true and false, v-if will completely destroy and reconstruct the element whereas v-show will simply toggle the CSS display property of that element to show and hide it.

Although these differences may not seem significant to you at the moment, they are worth keeping in mind when evaluating performance considerations for larger applications you develop. The VueJs guide summarizes it as follows:

Generally speaking, v-if has higher toggle costs while v-show has higher initial render costs. So prefer v-show if you need to toggle something very often, and prefer v-if if the condition is unlikely to change at runtime.

Rendering Lists in Vue with v-for

Let's assume we have an online store and wish to display the items we have in our inventory. The v-for directive allows us to render content based on the values of an array using a special syntax like so: item in inventory. This can be read as "for every item in inventory".

We will create this hypothetical inventory array and render it on the page using the v-for directive which will result in several li elements each containing the name and price of the item in our inventory:

...

<body>

<div id="vue-instance">
  <ul>
    <li v-for="item in inventory">
      {{ item.name }} - ${{ item.price }}
    </li>
  </ul>
</div>

<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

<script>
var vm = new Vue({
  el: '#vue-instance',
  data: {
    inventory: [
      {name: 'MacBook Air', price: 1000},
      {name: 'MacBook Pro', price: 1800},
      {name: 'Lenovo W530', price: 1400},
      {name: 'Acer Aspire One', price: 300}
    ]
  }
});
</script>

</body>

...

In reality we wouldn't be hard coding the inventory array in our application like that, instead we would be pulling this data from a database or an API endpoint which we will cover in a later tutorial.

Sometimes you may want to access the index of your loop which Vue provides 2 ways of doing:

Using the special $index variable:

<div id="vue-instance">
  <ul>
    <li v-for="item in inventory">
      {{ $index }} - {{ item.name }} - ${{ item.price }}
    </li>
  </ul>
</div>

or using an alias:

<div id="vue-instance">
  <ul>
    <li v-for="(index, item) in inventory">
      {{ index }} - {{ item.name }} - ${{ item.price }}
    </li>
  </ul>
</div>

Computed Properties

Computed properties are useful in scenarios where the value of one variable depends on one or more other variables. Take this trivial example as a use case for computed properties:

You provide the user with an input asking them for a number and you automatically return double that number. Typically you would have an event listener waiting for user input events on that input box and whenever an event fires, you would update the result with double that value. VueJs makes this sort of thing a lot more straight forward using computed properties:

...

<body>

<div id="vue-instance">
    <input type="number" v-model="x">
    result: {{ doubleX }}
</div>

<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

<script>
var vm = new Vue({
  el: '#vue-instance',
  data: {
    x: 1
  },
    computed: {
        doubleX: function(){
            return this.x*2;
        }
    }
});
</script>

</body>

...

The computed object is a set of functions that return a value and you can define it in the same way as we did earlier for the methods object in our Vue constructor.

Let's create a simple little game to show another example of computed properties: the user is asked to guess a number between 1 and 10 and if they get it right, then they will see a message saying 'You got it right!' and if they don't they will see 'Try again!'.

We will set the "random number" to 5 to begin with, and every time the user guesses, we will randomize this number. Using what we learned from the previous sections combined with computed properties, we can put this game together quite easily.

...

<body>

<div id="vue-instance">
    Guess a number between 1 and 10: <input type="number" v-model="userInput">
    <b>{{ message }}</b>
</div>

<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

<script>
    var vm = new Vue({
        el: '#vue-instance',
        data: {
            userInput: 0,
            randomNumber: 5
        },
        methods: {
            getRandomNumber: function(min, max){
                return Math.floor(Math.random() * (max - min + 1)) + min;
            }
        },
        computed: {
            message: function(){
                if (this.userInput == this.randomNumber) {
          this.randomNumber = this.getRandomNumber(1, 10);
                    return 'You got it right!';
                } else {
          this.randomNumber = this.getRandomNumber(1, 10);
                    return 'Try again!';
                }

            }
        }
    });
</script>

</body>

...

Wrapping Up

So there you have it! VueJs is, in my opinion, one of the easiest and most elegant libraries to learn. It is built on a solid set of design philosophies and is quickly growing in popularity. The library is small and simple enough to pick up rather quickly and get productive with. We covered the basics of VueJs in this tutorial with some examples to illustrate the key aspects, particularly:

  • Setting up VueJs and creating an instance with new Vue()
  • 2-way data binding with the v-model directive
  • Outputting data to the page using the double curly braces {{ }}
  • Rendering lists using the v-for directive
  • Conditional rendering with v-if and v-show
  • Event handling with v-on:* or it's shorthand @
  • Defining data, methods and computed properties

Now that you have the basics down, be sure to check out the other VueJs tutorials on coligo to continue building on your knowledge and fire up your favourite editor and start practicing!