A Student's Guide to Software Engineering Tools & Techniques »

Introduction to Vue

Authors: Chelsey Ong, Lu Lechuan
Reviewers: Gilbert Emerson, Ong Shu Peng

This chapter assumes that the reader has a basic knowledge of HTML and JavaScript.

What is Vue?

Vue is an open-source JavaScript framework for building user interfaces. It is designed to improve code quality and maintainability.

This is a simple example to show how easy it is to integrate VueJs into your web project:

The main HTML file:

<body>
  <div id="root">
    <h2>{\{ message }\}</h2>
  </div>
  <script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>
  <script src="the_path_to_the_javacript_file.js"></script>
</body>

This is inside the JavaScript file:

new Vue ({
  el: '#root',

  data: {
    message: "Hello World"
  }
});

Note that {\{ and }\} should be {{ and }} respectively, due to the limitations of MarkBind.

Step-by-step explanation of the code:

Step 1: Import Vue Content Delivery NetworkCDN and the JavaScript file in the main HTML file.

  <script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>
  <script src="the_path_to_the_javacript_file.js"></script>

Step 2: Create an instance of Vue (Vue is an object) in the JavaScript file; bind the instance to one of the component in our html file (e.g. create a component with id root and bind it with the instance of Vue).
In this case, only the root component can be accessed in Vue while the rest are unaffected. This is how we progressively plug in Vue into our projects.

  new Vue ({
    el: '#root',
  });
  <div id="root"></div>

Step 3: Specify our data (message: "Hello World") in the instance of Vue Class.

  data: {
    message: "Hello World"
  }

Step 4: Pass the message to the HTML file using double curly brackets.

  <div id="root">
    <h2>{\{message}\}</h2>
  </div>

Step 5: Open the browser and we will see "Hello World" being displayed:

Hello World


Vue Features

  1. Mutating of Data in the DOM
    In Vue, the state of the data can be directly modified.

    Let's say, there is a variable called message in your app. To modify message, you can do the following:

    this.message = 'Hello Space';
    

    When message is changed, the view will be re-rendered to show the new message. So you can say, the DOM is "reacting" to the changes in message.


  1. Two-way binding
    v-model is a Vue directive used to bind the DOM input field to its data variable.

    This allows the DOM variables and data to be "in sync", regardless of which one is being updated first. In other words, if you change the input value, the bound data will change, and vice versa.

    <input type="checkbox", v-model="isChecked">
      <label for="checked">Select</label>
    </input>
    

    When the checkbox is selected, isChecked is set to true. If the program sets isChecked to false, then checkbox will be unselected. This reduces any extra step required to manually update the data.

    2-way binding is useful for updating input form bindings such as checkboxes or drop-downs, where new data is entered by users and then updated in the view.


  1. Conditionals and Loops
    v-if allows you to conditionally insert/remove elements based on the truthfulness of the binding value.

    v-for allows you to loop through and render a list of items.

    Following the previous checkbox example, if you want to display a list of messages when the checkbox is checked, you can do the following:

    <div v-if="isChecked">
      <div v-for="message in messages">
        <li>{\{message}\}</li>
      </div>
    </div>
    

  1. Passing Data From Outer to Inner Components
    When you have components that are nested within each other, data is passed from the outer component to the inner component via props, where props are just custom data shared between the components.

    This follows the 1-way data flow encouraged by Vue, which ensures that data can only be changed by the component itself and also allows bugs to be easily traced in the code.

    To pass props to a Vue component, v-bind:<prop-name> is used. A demonstration of passing props is shown in the code segment below:

    Vue.component('todo-list', {
      props: ['item'],
      data: ['totalCount'],
      template:`
        <div class='todo-list'>
          <p>Total:{\{this.totalCount}\}</p>
          <p>{\{item.name}\}: {\{item.count}\}</p>
        </div>
      `
    })
    
    <todo-list
      v-for='item in items'
      v-bind:key='item.id'
      v-bind:item='item'
    ></todo-list>
    

    to-do list contains item, i.e. to-do list is the outer component and item is the inner component.

    Note that props is passed from the outer component to the inner component while data is kept private within a component.


  1. Emitting Events
    However, what if the user decides to update the item.count? The data for item.count has to be passed from item to todo-list so that totalCount can be updated inside todo-list .

    How do we do that if we have to follow the 1-way data flow rule?

    In situations where the inner component has to pass data back to the outer component, the inner component has to emit custom events and the outer component will update after listening to these events.

    You can think of emitting events like putting out a flyer about an event. If someone is interested in this event, he or she can gather more information through reading the flyer.

    Vue.component('item', {
      data: ['count', 'name'],
      template: `<button v-on:click="$emit('increased-count', count+1)">Increment item count</button>`
    })
    
    /* Inside todo-list component */
    template: `<item v-on:increased-count="updateCount" v-for="item in items"/>`
    

    When the button is clicked, the item component will emit a custom event named increased-count while the todo-list component listens for this event and executes its own updateCount method.


  1. Computed Properties
    This is useful when you want to compose new data based on the data that has changed. Instead of calling methods to do that whenever data has changed, computed properties will do it for you automatically.

    computed: totalCount() {
      return this.items.reduce((sum, item) => sum + item.count);
    }
    

    Unlike the use of methods, this updating of totalCount will only be triggered when the number of items in the list or any item's count changed.

    Since computed properties are cached and will not be processed every time the page refreshes, this can greatly improve the efficiency of your application.

    Note: computed properties must return the new data i.e. reactive properties. It cannot perform other operations in response to the change in data.

  1. Watched Properties
    Watched properties are used to call other functions when a particular data has been updated, such as independent operationsasynchronous operations.

    For example, when a new item is added, we want to send a notification to our friend to alert him or her about the change. A watched property on items can be added so that a notification can be sent whenever items has changed.

    watch: {
      totalCount: function() {
        this.totalCount = this.items.reduce((sum, item) => sum + item.count);
    
        // notify friend about the change
      }
    }
    

    This may look quite similar to Computed properties.

    To decide which is more suitable for your feature, here is a brief comparison:

    Watched property Computed property
    used for running expensive operations used for updating data for dependencies
    executed every time page refreshes uses cached data and executes only when changed
    watches for change in 1 property creates a new property that is updated when 1 or more dependencies change

  1. Lifecycle Hooks
    Every Vue instance goes through a series of initialization steps when it is created, i.e. setting up data observation, compiling the template, mounting the instance to the DOM, and updating the DOM when data modifies. Along these steps, Vue runs functions in the background called lifecycle hooks, allowing users to add code at each stage that could improve its rendering speed.

    The following diagram shows all lifecycle hooks and their specific execution stages:
    Figure 1. Vue's Lifecycle Diagram

    To run code at a specific stage, you can just define the corresponding hook function and add your code within the function. For example, the created hook can be used to run code right after the Vue instance is created:

    Vue.component('todo-list', {
      ...
      created: function() {
        console.log("to-do list is created.");
      }
    })
    

    For more detailed information about Vue lifecycle hooks, visit here.

Why use Vue?

Now that we know what Vue is, let us look at some benefits it has to offer.

Benefit 1: Approachable

Vue is very easy to learn. Compared to other framework such as Angular and React, Vue is simple in terms of API and design. Learning enough to build non-trivial applications typically takes less than a day. An example is provided below:

Iteration in React:

The JavaScript file in ReactJs

var Iteration = React.createClass({
  getInitialState() {
    return {
      array: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
    }
  },
  render() {
    this.state.array.map(function(date) {
      return (
        <span>{date}</span>
      )
    });
  }
});
ReactDOM.render(<Iteration />, document.getElementById('array'));

The HTML file in ReactJs

<div id="array"></div>

Iteration in Vue:

The JavaScript file in Vue

var Iteration = new Vue({
  el: '#array',
  data: {
    array: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
  }
});

The HTML file in Vue

<div id="array">
  <span v-for="date in array">{\{date}\}</span>
</div>

Benefit 2: Progressive

Vue is designed from the ground up to be incrementally adoptable. The core library is focused on the view layer only, and is easy to pick up and integrate with other libraries or existing projects. This means that if you have a large application, you can plug Vue into just a part of your application without disturbing the other components. A quote from Evan You - the founder of VueJs is as follows: > Vue is a more flexible, less opinionated solution (than Angular). That allows you to structure your app the way you want it to be, instead of being forced to do everything the Angular way (Angular requires a certain way to structure an application, making it hard to introduce Angular into an already built project). It’s only an interface layer so you can use it as a light feature in pages instead of a full blown SPA (single-page application). > > -- [source]

Benefit 3: Versatile

Vue is perfectly capable of powering sophisticated single-page applications when used in combination with modern tooling and supporting libraries.

Benefit 4: Clean

Vue syntax is simple and this can make the HTML pages very clean. This would allow user interfaces built by Vue to be more maintainable and testable.

Disadvantages of Vue

Like any other framework/library, Vue has its share of disadvantages.

  1. Relatively Small Size Community:
    Vue is a relatively new JavaScript framework as compared to Angular and React. The size of the community for Vue is therefore relatively small. Although small size community means you can differentiate yourself from other JavaScript developers, it also means there are fewer resources such as tutorials and problem-shooting guides.

  2. Language Barriers:
    A majority of users of Vue are the Chinese as Vue is developed by a Chinese American. He is supportive of the Chinese community and hence a lot of the existing plugins are written in Chinese. There might be some language barriers for an English speaking developer seeking for Vue resources.

Resources

Detailed comparison of Vue with other JavaScript frameworks can be found from:

Links to VueJs tutorials and practices: