JavascriptVue.jsweb designweb framework

Short Introduction to Vue.js

They announced Vue.js to me saying “It’s like Angular, only they did it right this time”. I don’t think there’s anything wrong with Angular, so my curiosity was piqued, and the stakes were high. What does Vue.js better than Angular? So I spend two afternoons playing around with Vue.js.

First impressions

Before starting to dig into the source code, let me share my first impressions with you. Vue.js is fast, it’s simple, and it’s easy to find info on the internet. I also felt that the error messages could be better, but then, that’s a typical beginner’s problem. In the early days, the error messages of Angular weren’t helpful at all. Vue.js is younger than Angular, so I guess they’ve done a good job here, too.

There were two pleasant surprises I didn’t expect. First, there’s a small but useful ecosystem. There’s tool support, there’s a small CLI to get started, and there’s even a browser plugin to help you debugging.

Second, there’s decent TypeScript support. At first glance, the source code seems to benefit a lot from the syntactical sugar of TypeScript. I always thought Vue.js was meant to be the successor of AngularJS, founded and supported by developers who didn’t accept the design choice of Angular 2. And one of the key choices was to embrace TypeScript. So TypeScript support comes as a surprise.

Scope of Vue.js

Before anybody starts a useless flame-war again, let’s have a look at the scope of Vue.js. It covers a rather limited scope. It supports the “V” of MVC. Everything else is up to you. Most people opt for third-party libraries. Some of these libraries (Vuex, the router, the CLI, and –
until recently – vue-resources) are maintained by the Vue.js team, so the scope of Vue.js is slightly larger than the scope of React.js, but even so, these libraries are optional.

Getting started

Your first Vue.js application is surprisingly simple:

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue"></script>
</head>
<body>
  <div id="app">
    {{ message }}
  </div>

  <script>
    var app = new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue!'
      }
    })
  </script>
</body>
</html>

Putting everything into a single HTML file is a good way to get started. It goes without saying that a large-scale application benefits from having a bit more structure and infrastructure. I’ll come back to that in a minute.

Actually, that’s the first example of the official Vue.js tutorial. The rest of the tutorial simply polishes the example. You can read it in one or two hours (faster, if you don’t run the source codes in your IDE). No wonder Vue.js is often called simple. There are only a few basic concepts, they are easy to pick up, and yet they are powerful.

Application and components

The first example is simply an application. Basically, that’s just the code you need to bootstrap your application. You’ll spend most of your time implementing components. Just in case you’re not familiar with the concept, consider my chess example:

In this particular case, even the layout exhibits a natural structure of the application. At the root is the application itself. Below, there are building blocks like the board, the game history, and the settings section. Most of these building blocks consist of a number of simpler building blocks themselves, such as chess pieces, chess fields, input fields, command buttons and so on. A simplified image of the component structure looks like so:

Anatomy of a component

Components usually consist of three items: an HTML template, some JavaScript code describing the behavior of the component, and optional CSS to fine-tune the layout of the component.

Vue.js allows you do put all three components in a single file, the *.vue file. Note that Vue doesn’t insist on doing so. You can put the entire application into a single HTML file, or you can split each component into three individual files. That seems to be a general pattern of Vue.js. There may be a recommended way to do things, but you’re free to follow your own path. In this case, the trail most developers follow is to use one *.vue file per component. In any case, Visual Studio code offers decent IDE support for *.vue files.

(Just for the record: I didn’t use any other IDE during my evaluation, so I can’t say anything about the other IDEs. Maybe they support Vue.js better, maybe they don’t. I just don’t know).

The template of the component describes what it looks like. So let’s start with the template:

<template>
<div>
  <div v-if="gameOver()">Game over!</div>
  <div>{{message}}</div>
 <table>
  <tr v-for="(row, rowindex) in grid.row" :key="rowindex">
    <td v-for="(cell, colindex) in row.cell" :key="colindex" 
        @click="toggleCell(rowindex, colindex)">
        <span class="field">{{content(rowindex, colindex)}}</span>
    </td>
 </tr>
</table>
</div>
</template>

Basically, that’s simple HTML code, plus a few additions. The template language of Vue.js follows the Angular tradition. In contrast to React.js, there’s no way to mix JavaScript with HTML.

Of course, the details of the syntax differ from Angular. In general, every Vue.js attribute (aka directive) starts with “v-“. The example above shows conditional rendering (v-if) and looping over an array (v-for).

The example also shows a JavaScript callback. @click tells Vue.js what to to when the component is clicked. The same principle applies to each other event, no matter if it’s a standard event such as @blur, @mouseover, or a custom event.

Events, properties, and state

Defining the behavior of a component

import GameEngine from './GameEngine';
import { Cell } from './Grid';
var engine = new GameEngine();

export default {
  name: 'TicTacToe',
  data() {
    return {
      message: "Let's play Tic Tac Toe!",
      gameOver: function() {
        return engine.gameOver;
      },
      content: function(rowindex, colindex) {
        let cell = engine.grid.row[rowindex].cell[colindex];
        if (cell === Cell.EMPTY) return '';
        if (cell === Cell.X) return 'X';
        return 'O';
      }
    };
  },
  methods: {
    toggleCell: function(rowindex, colindex) {
      this.message = engine.toggleCell(rowindex, colindex);
    }
  },
  computed: {
    ...
  }

Component state

Components combine state and behavior. In other words, there are properties and methods. Vue.js is heavily optimized with respect to the component state. At first glance, it’s similar to React.js. There’s unidirectional data flow, there’s the famous virtual DOM. At close inspection, you notice a few differences.

In the example above we’ve seen the data() function. After initializing this function, the object returned by the function is stored in the data variable of the Vue app.

The Vue.js methods are called with a special scope. Simplifying things a bit, this points to the data object. That’s why we can access the message variable by simply writing this.message in the example above.

Tracking changes

There’s more. Vue.js allows you to access the data object using the attribute syntax, but under the hood, it converts the attributes to properties. Every access to an attribute uses a getter or a setter. That, in turn, makes it easy to track changes. So Vue.js implements the virtual DOM in a very efficient way.

How Vue.js tracks changes. Image originally published on https://github.com/vuejs/vuejs.org/blob/master/src/images/data.png under an MIT license.
How Vue.js tracks changes. Image originally published on https://github.com/vuejs/vuejs.org/blob/master/src/images/data.png under an MIT license.

Another twist to improve performance are computed properties. The properties are something in between regular properties, which are basically local attributes of the component, and functions. Computed properties are updated when their input values change. Otherwise, they are just read from the cache.

Read the full stories here: Vue.js and reactivity and there: computed properties.

Modifying state from outside

A nice twist of Vue.js state is you can access it from outside. Vue.js not only defines the member variable data, it also allows you to modify it – within certain limits. That’s a feature that’s gone lost with Angular 2+. That, in turn, is the reason why I abandoned the AngularFaces project. Vue allows you to implement such projects. More generally speaking, you can implement applications interacting with JavaScript code outside the Vue.js application. In my eyes, that’s a big plus, although I suspect it’s one of the features hardly anybody uses. In any case, the feature makes it easier to integrate a Vue application into an existing application. Later, you can migrate the legacy application to a Vue application, converting one feature at a time.

By the way, that’s another advantage of the invisible (or transparent) getters and setters. Vue notices the changes to the data object, even if they are triggered by JavaScript code outside the Vue application.

Virtual DOM

I guess in 2018, almost everybody knows what a virtual DOM is. Suffice it to say that Vue.js uses a virtual DOM. It’s slightly different to the virtual DOM of React. The change detection algorithm is simplified by the transparent setters. This feature makes for a very effective change detection. It’s one of the reasons why Vue.js is considered a very fast framework.

Multiple Vue.js apps per page

If you’re integrating Vue.js into a legacy application or a portal server, you may need multiple Vue.js application on the same HTML page. Luckily, that’s one of the things Vue.js allows you to do. Vue.js starts up pretty fast, so more often than not, you can use as many Vue.js applications as you need on the same page.

Advanced state management

State management is one of the key pain points of the JavaScript world. That’s probably because nowadays everybody and their grandma expects rich applications, allowing for many interactions and no wait times. More often than not, virtually every screen element can influence almost every other screen element. That’s exactly what we tried to avoid in the past decades, and for a good reason. Actually, that’s why browser applications became so popular. The original request-response paradigm simplifies the programming model a lot. Too bad it also offers a bad user experience.

Libraries like Vue.js improve the user experience a lot. The drawback is you have to care a lot about events. In many cases, that’s not much of a problem. If you’re shipping form-based enterprise applications, you’ll probably cope with what Vue.js offers out-of-the-box.

However, if your application becomes very interactive, event management get tedious and error-prone. Despair not, the Vue.js team has something in store for you. Vuex is framework inspired by Redux. My first impression is that it shares many ideas with Redux while being slightly simpler. And it’s maintained by the Vue.js team itself. That takes a lot of the sting out of updating the core library. You don’t have to worry that the next update of Vue.js breaks Vuex.

Getting started with the CLI

Setting up a modern JavaScript application has become an art of its own. To make development simple again, Vue.js has a little CLI tool. It doesn’t do much. Basically, it cares only about a single job: creating a project.

The list of options exhibits a key property of Vue.js. It isn’t opinionated. It allows you to do things your way. In the case of the CLI, it creates the project using one of (at the time of writing) six template. You can also maintain custom templates.

Directory structure

I’ve created a simple tic-tac-toe game using the Vue.js CLI and the webpack template. As you can see in the screenshot on the right-hand side, the result is a fairly complex project, not unlike the project structure generated by the Angular CLI. In other words: it offers everything you need in a large-scale or enterprise project. If that looks a bit over-the-top to you, choose one of the simpler templates.

The build folder is collapsed in the screenshot, but it’s remarkable because it contains the webpack configuration. So the Vue CLI generates a project you can simply use without having to learn anything about webpack. But if you need to, you can always dive into the gory details of how the project is built and add your tweaks. For example, John Papa uses the webpack configuration to add TypeScript support to an existing Vue.js project. As it turns out, this requires just a few simple steps.

Local CSS

Vue.js components optionally contain “scoped CSS”. That’s CSS code applying only to this component. That’s a similar approach to the local CSS of Angular, but it’s a difference to React.js. React requires you to use a third-party library to use local CSS.

If you prefer to use SASS or SCSS, you can do so by adding a few lines to the configuration files of the webpack CLI project, as described in Mahesh’s article.

Router

Vue.js also includes a router. It’s maintained by the Vue.js team, but like Vuex, it’s an optional module you can add or not. Defining the routes is pretty straightforward. It’s a Json object listing the routes and the corresponding component classes, like so:

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/tictactoe',
      name: 'TicTacToe',
      component: TicTacToe
    },
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
});

The router also supports parameters (like “/tictactoe/savedGame/:filename”). It even supports regular expressions to match the path to the URL.

Learning curve and documentation

Many sources claim it’s very easy to learn Vue.js. I’ve only been playing with Vue.js for a couple of days now. Even so, I feel surprisingly fluent with Vue.js. First, you can start small. You don’t have to know many features to use Vue.js. Second, there’s not too much to learn. Vue.js has a limited scope, so you can pick it up a lot faster than, say, Angular.

Truth to tell, that’s probably a wrong impression. Granted, you have to learn a lot of stuff just to use Angular, but in the long run, you need all this stuff. It requires less effort to learn Vue.js, but after that, you still need solutions for many things Angular solves out-of-the-box. Like so often, the complexity doesn’t go away by choosing a different library. Unless you don’t need all those fancy features. Large-scale enterprise applications have different requirements than, say, applications like Google Mail or Facebook. “One size fits all” doesn’t work when it comes to web applications.

What’s really great about Vue.js is the documentation. My first impression (remember: only a couple of days) is that you find answers to every rookie question. Even better, most answers are excellent.

Wrapping it up

There’s a reason why Vue.js is gaining so much traction. As to my impression, it’s every bit as powerful as React.js while being a bit simpler. Vue.js has an awesome documentation, and it’s supported by a good ecosystem, both with respect to tools and libraries. If you’ve got a small or medium single-page-application, you can’t go wrong with Vue.js. It’s also suited for major applications. Only in the case of large-scale form-based enterprise applications, I still prefer Angular. Little wonder the WordPress team considers adopting Vue.js as a standard framework for WordPress. It’s small footprint, ease of use, and fast start-up time make it ideal for adding it to an existing web application.


Dig deeper

Vue.js project page (including documentation, getting started guides and more).

One thought on “Short Introduction to Vue.js

  1. Recently I read an article on slashdot giving Stack overflow’s analysis of javascript frameworks https://developers.slashdot.org/story/18/01/13/0117235/stack-overflow-stats-reveal-the-brutal-lifecycle-of-javascript-frameworks?utm_source=rss1.0mainlinkanon&utm_medium=feed. Their take is that all these Javascript frameworks will eventually die, but a lot of the comments pointed out that SO’s statistical analysis is flawed. Mostly due to the fact that people stop posting on SO once problems have been solved successfully. And the less problems you have with a framework the less you need SO.

Leave a Reply

Your email address will not be published.