Vue.js 2 Cookbook

5 (7 reviews total)
By Andrea Passaglia
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Getting Started with Vue.js

About this book

Vue.js is an open source JavaScript library for building modern, interactive web applications. With a rapidly growing community and a strong ecosystem, Vue.js makes developing complex single page applications a breeze. Its component-based approach, intuitive API, blazing fast core, and compact size make Vue.js a great solution to craft your next front-end application.

From basic to advanced recipes, this book arms you with practical solutions to common tasks when building an application using Vue. We start off by exploring the fundamentals of Vue.js: its reactivity system, data-binding syntax, and component-based architecture through practical examples.

After that, we delve into integrating Webpack and Babel to enhance your development workflow using single file components. Finally, we take an in-depth look at Vuex for state management and Vue Router to route in your single page applications, and integrate a variety of technologies ranging from Node.js to Electron, and Socket.io to Firebase and HorizonDB.

This book will provide you with the best practices as determined by the Vue.js community.

Publication date:
April 2017
Publisher
Packt
Pages
454
ISBN
9781786468093

 

Chapter 1. Getting Started with Vue.js

In this chapter the following recipes will be covered:

  • Writing Hello World with Vue.js
  • Writing lists
  • Creating a dynamic and animated list
  • Reacting to events such as clicks and keystrokes
  • Choosing a development environment
  • Formatting your text with filters
  • Debugging your application with mustaches (for example, a JSON filter)
  • X-raying your application with Vue developer tools
  • Upgrading to Vue.js 2
 

Introduction


Vue is a very powerful framework but one of its strengths is that it is very lightweight and easy to pick up. As a matter of fact, in the first recipe you will build a simple but functioning program in minutes, with no setup required.

In this chapter, you will learn lists which will help you create web pages where an element is repeated (like a catalog). Furthermore, you will build an interactive page with event listeners.

Some development environments are presented so you can choose the one that suits you better; you will use some debugging tricks that will give you a head start when developing your own code and better insight to kill bugs in your apps.

Please note that, at the time of writing, ES5 is the most well supported standard for JavaScript in browsers. In this chapter, I will use ES5 so you can follow along even if your browser does not support the newer ES6. Remember though that in following chapters ES6 will be used. By now, Chrome is compatible with most ES6 important constructs, but in general you should use Babel to make your app compatible with older browsers. Refer to the recipe How to use Babel to compile from ES6 in Chapter 8, Organize + Automate + Deploy = Webpack, when you are ready to use Babel.

 

Writing Hello World with Vue.js


Let's create the simplest possible program in Vue.js, the obligatory Hello World program. The objective here is to get our feet wet with how Vue manipulates your webpage and how data binding works.

Getting Ready

To complete this introductory recipe, we will only need the browser. That is, we will use JSFiddle to write our code:

If you have never used JSFiddle, don't worry; you are about to become an expert frontend developer and using JSFiddle will become a handy tool in your pocket:

  1. Head your browser to https://jsfiddle.net:

You will be presented with a blank page divided into quadrants. The bottom-left is where we will write our JavaScript code. Going clockwise, we have an HTML section, a CSS section, and finally our preview of the resulting page.

Before beginning, we should tell JSFiddle that we want to use the Vue library.

  1. In the top-right part of the JavaScript quadrant, press the cogwheel and select Vue 2.2.1 from the list (you should find more than one version, "edge" refers to the latest version and at the time of writing corresponds to Vue 2).

We are now ready to write our first Vue program.

How to do it...

  1. In the JavaScript section, write:
        new Vue({el:'#app'})
  1. In the HTML quadrant, we create the <div>:
        <div id="app">
          {{'Hello ' + 'world'}}
        </div>

 

  1. Click the Run button in the upper-left corner; we see the page greeting us with Hello world:

How it works...

new Vue({el:'#app'}) will instantiate a new Vue instance. It accepts an options object as a parameter. This object is central in Vue, and defines and controls data and behavior. It contains all the information needed to create Vue instances and components. In our case, we only specified the el option which accepts a selector or an element as an argument. The #app parameter is a selector that will return the element in the page with app as the identifier. For example, in a page like this:

<!DOCTYPE html> 
<html> 
  <body> 
    <div id="app"></div> 
  </body> 
</html>

Everything that we will write inside the <div> with the ID as app will be under the scope of Vue.

Now, JSFiddle takes everything we write in the HTML quadrant and wraps it in body tags. This means that if we just need to write the <div> in the HTML quadrant, JSFiddle will take care of wrapping it in the body tags.

Note

It's also important to note that placing the #app on the body or html tag will throw an error, as Vue advises us to mount our apps on normal elements, and its the same thing goes for selecting the body in the el option.

The mustaches (or handlebars) are a way to tell Vue to take everything inside them and parse it as code. The quotes are a normal way to declare a literal string in JavaScript, so Vue just returns the string concatenation of hello and world. Nothing fancy, we just concatenated two strings and displayed the result.

There's more

We can leverage that to do something more interesting. If we were aliens and we wanted to greet more than one world at a time, we could write:

We conquered 5 planets.<br/> 
{{'Hello ' + 5 + ' worlds'}}

We may lose track of how many worlds we conquer. No problem, we can do math inside the mustaches. Also, let's put Hello and worlds outside brackets:

We conquered {{5 + 2}} planets.<br/> 
Hello {{5 + 2}} worlds

Having the number of worlds as raw numbers inside the mustaches is just messy. We are going to use data binding to put it inside a named variable inside our instance:

<div id="app"> 
  We conquered {{countWorlds}} planets.<br/> 
  Hello {{countWorlds}} worlds 
</div>

new Vue({ 
  el:'#app', 
  data: { 
    countWorlds: 5 + 2 
  } 
})

This is how tidy applications are done. Now, every time we conquer a planet, we have to edit only the countWorlds variable. In turn, every time we modify this variable, the HTML will be automatically updated.

Congratulations, you completed your first step into the Vue world and are now able to build simple interactive applications with reactive data-binding and string interpolation.

 

Writing lists


The desire to produce lists almost seems to be an innate part of human nature. There is a deeply satisfying feeling that one obtains by watching a well ordered list marching down the computer screen.

With Vue, we are given the tools to make lists of any kind with a stunning appearance and maximum ease.

Getting Ready

For this recipe we are going to use basic data-binding, if you follow the very first recipe you are already familiar with it.

How to do it...

We are going to build lists in a couple of different ways: with a range of numbers, with an array, and finally with an object.

Range of numbers

To start off with lists, set up your JSFiddle like in the preceding recipe, adding Vue.js as a framework. Select Vue 2.2.1 (or Vue (edge)):

  1. In the JavaScript section, write:
        new Vue({el:'#app'})

 

  1. And in the HTML write:
        <div id="app"> 
          <ul> 
            <li v-for="n in 4">Hello!</li> 
          </ul> 
        </div>

This will result in a list with Hello! written four times. In a few seconds your first list is complete, nice job!

We can write a countdown with this technique--in the HTML, replace the content of the <div> with the following:

<div id="app"> 
  <ul> 
    <li v-for="n in 10">{{11-n}}</li> 
    <li>launch missile!</li> 
  </ul> 
</div>

Arrays

  1. In the HTML, to achieve the same result, edit the list to reflect the following:
        <ul> 
            <li v-for="n in [10,9,8,7,6,5,4,3,2,1]">{{n}}</li> 
            <li>launch missile!</li> 
        </ul>

Although this list is identical to the previous one, we shouldn't put literal arrays in HTML markup.

  1. We're better off with a variable that contains the array. Edit the preceding code to match the following:
        <ul> 
          <li v-for="n in countdown">{{n}}</li> 
          <li>launch missile!</li> 
        </ul>

 

  1. Then put the array countdown in the JavaScript:
        new Vue({ 
          el:'#app', 
          data: { 
            countdown: [10,9,8,7,6,5,4,3,2,1] 
          } 
        })
Arrays with index notation

When enumerating an array, we also have access to the index, represented by the variable i in the following code:

  1. The HTML becomes:
        <div id="app"> 
          <ul> 
            <li v-for="(animal, i) in animals">
              The {{animal}} goes {{sounds[i]}}
            </li> 
          </ul> 
        </div>
  1. In the code part, write:
        new Vue({ 
          el: '#app', 
          data: { 
            animals: ['dog', 'cat', 'bird'], 
            sounds: ['woof', 'meow', 'tweet'] 
          } 
        })

Objects

The preceding example can be refactored to match animal names and their sounds so that an accidental misalignment of the index will not affect our list.

  1. The HTML becomes:
        <div id="app"> 
          <ul> 
            <li v-for="(sound, name) in animals"> 
              The {{name}} goes {{sound}} 
            </li> 
          </ul> 
        </div>
  1. And we need to create the animals object in the JavaScript:
        new Vue({ 
          el: '#app', 
          data: { 
            animals: { 
              dog: 'woof', cat: 'meow', bird: 'tweet' 
            } 
          } 
        })

How it works...

The workings of lists are quite simple; here is a little more explanation on the syntax.

Range of numbers

The variable n is in scope inside the <li> tag. To prove it to yourself, you can quickly build a countdown list as follows:

<ul> 
  <li v-for="n in 10">{{11 - n}}</li> 
  <li>launch missile!</li> 
</ul>

We write 11 instead of 10 because enumeration in Vue is 1-indexed; this means that n in 10 will start to count from 1, not from 0 like someone might expect, and go up to 10. If we want our countdown to start from 10, then we have to put 11. The last number will be 10, so we'll have 1 as the last number before the missile is launched.

What v-for="n in 10" does is call enumeration; specifically we are enumerating a range of numbers (1 to 10).

Arrays

Vue allows us to enumerate arrays too. The general syntax is as follows:

v-for="(element, index) in array"

As seen, the index and parenthesis can be omitted if all we want are the array elements.

This form of enumeration is guaranteed to be ordered. In other words, the ordered sequence of elements in the array will be the same you will see on the screen; this is not the case when enumerating objects.

 

Objects

The syntax is v-for="(value, property)" and if you want you can also squeeze in the index with v-for="(value, property, index)". The latter is not recommended though since, as already said, the order in which properties are enumerated is not fixed. In practice, in most browsers, the order is the same as the insertion order but this is not guaranteed.

 

Creating a dynamic and animated list


In Vue most data is reactive. In practice this means that if something is going to change in our view-model, we will see the results immediately. This is what lets you concentrate on the app itself, leaving aside all the drawing logic. In this recipe, we are also going to acknowledge some limitations of this system.

Getting Ready

To complete this recipe, you should know how to use basic data-binding (introduced in the very first recipe) and how to create lists (second recipe).

How to do it...

In the previous recipe we built a list for a countdown for a missile launch:

<div id="app"> 
  <ul> 
    <li v-for="n in countdown">{{n}}</li> 
    <li>launch missile!</li> 
  </ul> 
</div>
new Vue({
  el:'#app',
  data: {
    countdown: 
      [10,9,8,7,6,5,4,3,2,1]
  }
})

Wouldn't it be great if it was animated? We can tweak the JavaScript to add numbers to countdown as seconds pass:

  1. Copy the preceding code in the HTML and JavaScript sectors of JSFiddle, with the exception that we will fill the countdown ourselves, so set it to an empty array.

To get hold of the countdown variable we must pass the variable through the Vue instance itself.

  1. Assign the Vue instance to a variable for later reference:
        var vm = new Vue({
          el:'#app',
          data: {
            countdown: []
          }
        })

This way we can use vm to access the Vue instance.

  1. Initialize the countdown from 10:
        var counter = 10
  1. Set up a function that repeatedly adds the number of remaining seconds to the now empty countdown array:
        setInterval(function () { 
          if (counter > 0) { 
            vm.countdown.push(counter--) 
          } 
        }, 1000)

How it works...

What we are going to do is get a reference of the countdown array and fill it with decrementing numbers with the help of setInterval.

We are accessing countdown through the vm variable we set in the line vm.countdown.push(counter--), so our list will get updated every time we add a new number to the array.

This code is very simple, just note that we must use the push function to add elements to the array. Adding elements with the square brackets notation will not work:

vm.countdown[counter] = counter-- // this won't work

The array will get updated, but this way of assignment will skip Vue's reactive system due to how JavaScript is implemented.

There's more

Running the code now will add countdown numbers one at a time; great, but what about the final element launch missile? We want that to appear only at the end.

To do that here is a little hack we can do directly in HTML:

<ul> 
  <li v-for="n in countdown">{{n}}</li> 
  <li>{{ countdown.length === 10 ? 'launch missile!' : '...' }}</li> 
</ul>

This solution is not the best we can do; learn more in the recipe on v-show.

We just learned that we cannot add elements to a reactive array with the brackets notation if we want it to update in the view. This is true also for the modification of elements using brackets and for manually changing the length of the array:

vm.reactiveArray[index] = 'updated value' // won't affect the view 
vm.reactiveArray.length = 0 // nothing happens apparently

You can overcome this limitation using the splice method:

vm.reactiveArray.splice(index, 1, 'updated value') 
vm.reactiveArray.splice(0)
 

Reacting to events such as clicks and keystrokes


A fundamental part of every application is the interaction with the user. Vue has shorthand to intercept most user events and connect them to relevant actions.

Getting Ready

To successfully complete this recipe, you should know how to create a list. If you don't, check out recipe Filtering a list with a computed property in Chapter 2, Basic Vue.js Features.

How to do it...

The following bit of code shows how to react to a click event:

  1. Fill in the following HTML:
        <div id="app"> 
          <button v-on:click="toast">Toast bread</button> 
        </div>
  1. As for the JavaScript, write the following:
        new Vue({el:'#app', methods:{toast(){alert('Tosted!')}}})
  1. Run the code! An event listener will be installed on the button.
  2. Click the button and you should see a popup that says Toasted!

How it works...

Running the preceding code will install an event handler on the button. The syntax is v-on:DOMevent="methodEventHandler". The handler must be a method, that is, a function in the methods option. In the preceding example, toast is the handler.

Two-way data binding

The v-on attribute will have you covered in most cases, especially if the event comes from the element. On the other hand, it may sometimes be too verbose for some tasks.

For example, if we had a textbox and we wanted to update a variable with the content of the textbox and ensure that the textbox always has an updated value of the variable (which is called two-way data binding), we would have to write a couple of handlers.

Instead, this operation is carried out by the v-model attribute, as the following code shows:

<div id="app"> 
  <button v-on:click="toast">Toast bread</button> 
  <input v-model="toastedBreads" /> 
  Quantity to put in the oven: {{toastedBreads}} 
</div>

new Vue({ 
  el: '#app', 
  methods: { 
    toast () { 
      this.toastedBreads++ 
    } 
  }, 
  data: { 
    toastedBreads: 0 
  } 
})

Play a little with this application and notice how no handler is necessary to keep the textbox in sync. Every time toastedBreads is updated, the text will update too; conversely, every time you write a number, the quantity gets updated as well.

There's more

If you followed the first recipe in this chapter, you'll remember how we greeted a variable number of worlds; we can make the experience more interactive. Let's build a list of planets we'd like to greet:

<div id="app"> 
  <ul> 
    <li v-for="world in worlds">{{world}}</li> 
  </ul> 
</div>

new Vue({ 
  el: '#app', 
  data: { 
    worlds: ['Terran', 'L24-D', 'Ares', 'New Kroy', 'Sebek', 'Vestra'] 
  } 
})

We want to be able to keep track of newly conquered worlds and delete the ones we destroy. This means adding and removing elements from the list. Consider the following HTML:

<ul> 
  <li v-for="(world, i) in worlds"> 
    {{world}} 
  <button @click="worlds.splice(i, 1)">Zap!</button> 
  </li> 
</ul> 
<input v-model="newWorld"/> 
<button @click="worlds.push(newWorld)">Conquer</button>

Here the @ symbol is the shorthand for v-on: Let's examine the modifications:

  • We added a button to remove the planet (we needed to write out the index in the v-for)
  • We placed a textbox that is bound to the data variable newWorld
  • We placed a corresponding button that adds what's inside the textbox to the list

Running this code will work. But if you look at the console, you will see a warning when you update the text field:

[Vue warn]: Property or method "newWorld" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in root instance)

This is because we never declared newWorld in our Vue instance, but that's easy to fix:

new Vue({ 
  el: '#app', 
  data: { 
    worlds: ['Terran', 'L24-D', 'Ares', 'New Kroy', 'Sebek', 'Vestra'], 
    newWorld: '' 
  } 
})
 

Choosing a development environment


We are going to explore some different styles of developing, from the naive JSFiddle approach, to a more robust approach with WebStorm support. Since we want to use libraries to add new functionalities to our software, I'll provide you with a guide to add them regardless of whichever method of development you choose.

How to do it...

I will start from the simplest method and then present you some more involved methods for bigger projects.

Just the browser

There are a series of websites such as JSFiddle that let you write a Vue application right from the browser (CodePen and JS Bin among others) and those are very good to test new functionalities and try recipes in this book. On the other hand, they are too limited in terms of code organization to develop anything more. In first recipe of this chapter, this style of development is used so please refer to that to learn how to develop with only the browser. In general, you should take what you learn by doing the recipes this way and transfer it into more structured projects, depending on what you are developing.

Adding dependencies with just the browser

Every time I mention an external library, you will search for the relative .js file on the Internet, preferably distributed by a CDN, and add it to the left menu of JSFiddle. Let's try with moment.js.

  1. Open a new JSFiddle (point your browser to https://jsfiddle.net/).
  2. In another tab, search for momentjs CDN in your favorite search engine.
  3. The first result should lead you to a CDN website with a list of links; you should eventually find something like https://somecdn.com/moment.js/X.X.X/moment.js where the X represents the version number.
  4. Copy the link you found and go back to JSFiddle.
  5. In the External Resources section in the left sidebar, paste your link and press Enter.

For many libraries this is sufficient; some libraries do not support this and you will have to include them in your JSFiddle in some other way.

TextEditor

The rawest way to be up and running is with a text editor and a browser. This is totally legitimate for simple, self contained components.

There are plenty of text editors from which to choose these days. One I like to use is Microsoft Visual Studio Code (https://github.com/Microsoft/vscode). There is little difference if you use another, is just so happens that Code has a plugin for Vue:

  1. Create a new file called myapp.html, in which we write:
        <!DOCTYPE html> 
        <html> 
          <head> 
            <title>Vue.js app</title> 
          </head> 
          <body> 
            <div id="app"> 
              {{'hello world'}} 
            </div> 
            <script 
              src="https://cdnjs.cloudflare.com/ajax
               /libs/vue/2.0.0/vue.js">
            </script> 
            <script> 
              new Vue({el:'#app'}) 
            </script> 
          </body> 
        </html>
  1. Open the file you just created in a browser.

Vue gets downloaded from https://cdnjs.com/ and the text hello world should appear (without mustaches--if you see the mustaches, chances are something's gone wrong so check the console for errors).

This approach resembles the JSFiddle one: we have an HTML part, a JavaScript part, and a CSS part on the top. We are just bringing everything under our control. Also, this way we can use Vue developer tools (check out the recipe X-raying your application with Vue developer tools for an introduction of those).

 

Adding dependencies with a TextEditor

Adding external libraries in this configuration means simply adding another <script> entry to your file and setting the source attribute to the respective link. If we wanted to add moment.js, we look for the library in the same way as explained before and we add the following snippet to our page:

<script src="https://somecdn.com/moment.js/X.X.X/moment.js "></script>

Note

Please note that you have to paste the link you found instead of the fake one mentioned in the preceding snippet.

Node package manager (npm)

The canonical way to work with Vue projects, and the one officially supported by the Vue community, involves the use of npm and in particular an npm package named vue-cli.

If you are not familiar with npm, put it on your list of things to do, especially if you plan to develop with JavaScript extensively.

Briefly stated, npm is a tool to organize and share your code, beyond using other people's code in your projects. More formally, it's a package manager for everything JavaScript. We will use some basic commands now and some more advanced later in the book, but you are invited to learn more by yourself:

  1. Install npm. As it's bundled in Node.js, the best route to follow is to install Node.js directly. You will find instructions at https://nodejs.org/en/download/.
  2. After you install npm, open a command line and type npm install -g vue-cli; this will install vue-cli. The -g options stands for globally and it means that wherever you are, you can type vue and it will run the program.
  3. Create a new directory that will act as a workspace. We will put all of our projects inside it.
  4. Type vue list; we get all the available templates from the official Vue template repository--other templates can be used from other sources.

The simple template will create a page similar to what we have done a few paragraphs before. I invite you to run vue init simple and check it out; spot the difference between that and what we have done. What we are doing now instead is a step further. We are going to use a more involved template that includes a bundler. There is one for webpack and browserify; we are going with the first.

If you are not familiar with webpack or browserify they are programs to control the build process of JavaScript programs from sources and assets (images, css files, and others) to customized bundles. For example, for a single .js file:

  1. Type vue init webpack-simple and the program will ask you some questions on how you would like your project to be. If you don't know how to answer, press Enter to go with the default.

We could have chosen in an equivalent way the browserify-simple template; those are two different libraries to achieve the same results.

  1. Once the scaffolding is complete, type npm install. This will take care of downloading and installing all the npm packages we need to write our Vue app.

After this, you'll have a functioning demo application already in place.

  1. Type npm run dev to run your application. Further instruction, will appear on the screen and will tell you to visit a specific web address, but there is a good chance that your browser will be opened automatically.
  2. Point the browser at the specified address. You should be able to see the demo application right away.

Exploring the source files created by vue-cli, you will find two notable files. The first file is the entry point for your application, src/main.js. It will contain something like the following:

import Vue from 'vue' 
import App from './App.vue'

new Vue({ 
 el: '#app', 
 render: h => h(App) 
})

This code was loaded in the index.html page you just saw. It just tells the main Vue instance to load and render the App component in an element selected by #app (the element with the attribute id="app", a <div> in our case).

The App.vue file you will find is a self contained way you can write Vue components. You will find more on components in other recipes, but for now think of it as a way you can further divide your application to keep it more ordered.

The following code is different from what you'll find in the official template but it summarizes the general structure:

<template> 
  <div id="app"> 
    <img src="./assets/logo.png"> 
    <h1>\{{ msg }}</h1> 
  </div> 
</template>
<script> 
export default { 
  data () { 
    return { 
      msg: 'Hello Vue 2.0!' 
    } 
  } 
} 
</script> 
<style> 
body { 
  font-family: Helvetica, sans-serif; 
} 
</style>

You can see that having code divided into HTML, JavaScript, and CSS is a recurring pattern. In this file we can see something similar to what we saw in JSFiddle in the first recipes.

In the <template> tag we put our HTML, in the <script> tag JavaScript code and we use the <style> tag to add some styling to our application.

After running npm run dev, you can try to edit the msg variable in this file; the webpage will reload the component automatically after saving your modifications.

 

Adding dependencies with npm

To add external libraries in this configuration you simply type npm install followed by the name of the library. Then in your code you use it with something along the lines of the following:

import MyLibrary from 'mylibrary'

We can import moment.js with the following command:

npm install moment

Then in our JavaScript we add the following lines:

import moment from 'moment'

IDE

If you have a very big project, chances are you are already using tools such as IntelliJ or Webstorm. In this case, I suggest you stick to the embedded console for most of the work and only use features such as syntax highlighting and code completion. This is because developer tools are still immature for Vue and you will probably spend more time configuring your tools than actually programming:

  1. Open Webstorm and create a new Empty Project:
  1. In the bottom-left corner you should be able to open up the console or Terminal:
  1. From this prompt you should be able to work with npm exactly as explained in the previous paragraph. Read it if you haven't yet. In our case, we are going to suppose Node is installed and vue-cli is also installed.

 

  1. Type vueinit simple and answer the questions; you should end up with something similar to this:
  1. Open the index.html file by double-clicking it.
  2. Hover over the top-right corner of the index.html file, and you should see the browser icons; click one:
  1. Your sample application is up and running!

Wrap up

You can see more of how this works in dedicated recipes. Here I wanted you to have an overview of the possibilities for developing with Vue. For quick prototypes, you can definitely go with JSFiddle. When you need your own environment or you need to use Vue developer tools but not much more, using just a text editor can be acceptable. For the majority of serious projects though, you should familiarize yourself with npm, webpack, or Browserify and use vue-cli to scaffold your new projects.

 

Formatting your text with filters


The first version of Vue came bundled with some text filters that helped format text and solve some common problems.

In this new version, there are no built-in filters (except the equivalent of the JSON filter covered in the next recipe). I think this is because it's very easy to write your own filter and also very easy to find online libraries that do a much better job in specialized situations. Finally, filters have somewhat changed purpose: they are more for post-processing now and less for actual filtering and sorting arrays.

To demonstrate how easy it is to create a filter, we will recreate a filter of the old version of Vue: capitalize.

Getting Ready

You don't need any particular knowledge to complete this recipe.

How to do it...

Sometimes we have some strings floating around in our variables like labels. When we put them in the middle of a sentence they work fine, but on the other hand they don't look very good at the beginning of a sentence or bullet point.

We want to write a filter that will capitalize whatever string we put into it. If, for example, we want the string hello world to start with a capital H, we'd like to be able to write:

{{'hello world' | capitalize }}

If we try to run this as HTML in a Vue app, it will complain [Vue warn]: Failed to resolve filter: capitalize.

Let's create the filter and add it to Vue's internal list of filters:

  1. Write the following JavaScript to register a filter and instantiate Vue:
        Vue.filter('capitalize', function (string) { 
          var capitalFirst = string.charAt(0).toUpperCase() 
          var noCaseTail = string.slice(1, string.length) 
            return capitalFirst + noCaseTail 
        }) 
        new Vue({el:'#app'})
  1. In the HTML section, write:
        {{'hello world' | capitalize }}
  1. Run your code and notice how the text now reads Hello world.

How it works...

The pipe sign indicates that the following is the name of a filter; in our case capitalize is not in Vue's list of filters, hence the warning. Vue will print the string as is.

What Vue will do before even starting is register our filter (with Vue.filter) in its asset library. Vue has an the internal filters object and will create a new entry: capitalize. Every time it sees the pipe symbol it will look for a corresponding filter. Remember to write it before the actual instantiation of a Vue instance because otherwise Vue will not find it.

The working of the filter is very basic JavaScript, in fact, a better way to write this filter with ES6 would be:

Vue.filter('capitalize', function (string) { 
  var [first, ...tail] = string 
  return first.toUpperCase() + tail.join('') 
})

If you are not familiar with ES6, here is a brief explanation. The second line is called a destructuring assignment of string; in particular we are interpreting string as an array of characters, separating the first character into first and putting all the other characters in tail. This is a faster way to assign different parts of an array to multiple variables. The other thing that may seems mysterious is that join(''). Since tail is now an array of characters, we need some means to re-join the single letters into a compact string. The argument of join represents a separator between the single characters. We don't want any, so we pass an empty string.

In the next chapter, you will find more recipe for filters and cover other real use cases.

 

Debugging your application with mustaches (for example, a JSON filter)


In the previous recipe, we had a complete overview of filters and we said that Vue comes with no built-in filters except for an equivalent of the JSON filter. This filter was very useful and, while its considered not really orthodox to debug with it, sometimes it just makes your life easier. Now we have it straight away without even writing it.

How to do it...

To see it in action, we can simply display the value of an object in our Vue instance.

  1. Write the following JavaScript:
        new Vue({ 
          el: '#app', 
          data: { 
            cat: { 
              sound: 'meow' 
            } 
          } 
        })

This just creates a cat object in our code with a string inside.

  1. Write the following HTML:
        <p>Cat object: {{ cat }}</p>

 

  1. Run your app and notice how the cat object is outputted in all it's beauty, just like JSON.stringify.

How it works...

Cat will display the content of the cat object. In the old Vue, to get this result we had to write {{ cat | json }}.

A thing to be wary of is loops in our objects. If our object contains a circular reference, and you wrap it in mustaches, this will not work. These objects are more common than you would think. HTML elements, for example, are JavaScript objects that contain references to a parent node; the parent node in turn contains a reference to its children. Any such tree structure would cause the mustaches to print an infinite description of the object. When you actually do it, Vue simply throws an error and refuses to work. The error you would see in the console is actually thrown by the internal method used to print the JSON.stringify object.

A practical situation in which using mustaches could be useful is when the same value is changed in several places, or when you want to quickly check the content of a variable. Mustaches can be useful even for demonstrational purposes, as it's clear from the usage you will see in this book.

 

X-raying your application with Vue developer tools


Using mustaches is a quick way to display the content of an object. However it has some limitations; one of them outlined in the previous recipe is that, out of the box, it breaks when dealing with objects that contain circular references. A tool that doesn't present this limitation when inspecting internal variables and that sports many more debugging features is Vue developer tools. There's a Chrome extension that will help you at every step of development, visualizing the state of your components, where they are in the page, and more. It's also deeply integrated with Vuex (covered in later recipes) and has a time machine feature that lets you rewind the event flow directly from the browser.

 

Getting Ready

To install it, you just have to download the extension from the Chrome Web Store in the extensions category. Just look for Vue.js devtools and you'll find it right away, press the ADD TO CHROME button, and you're set to go:

Unfortunately you won't be able to use it in some configurations; particularly it currently doesn't seem to work in iframe environments and JSFiddle is one of them, so to see it you have to at least use the one page approach outlined in the Choosing a development environment recipe. .

 

How to do it...

  1. Access the Developer Tools of Chrome (Usually with cmd + opt + I or Ctrl + Shift + I) and you will see a new tab at the end that says Vue. Clicking it will bring forth the developer tools.

Note

To make it work for pages opened via the file:// protocol, you need to check Allow access to file URLs for this extension in Chrome's extension management panel.

You will be presented with a hierarchical tree of components laid out in your page and by selecting them you will be able to see all the variables in depth and in real time.

  1. Click on the various objects in the three to see details:

Also, you will see a useful button: the inspect DOM button (the eye) will scroll the page to where the element is and will show you the DOM representation in the Chrome developer tools. Furthermore, when you click on a component (root in the illustration) you will have a variable like $vm0 available to be used in the console. For example, you can execute methods or inspect variables.

  1. Click on the root component and write the following in the console to explore the $vm0.docsUrl property:
 

Upgrading to Vue.js 2


If you need to upgrade your Vue app to version 2, most of your code is good to go. There are a couple of features though that need some modifications. Some are simple renaming, some are more involved.

How to do it...

To give your migration a head start; Chris Fitz (a member of the Vue core team) created a little helper app that will scan your code and guide you in the migration:

  1. Install Vue Migration Helper with the following npm command:
        npm install -g git://github.com/vuejs/vue-migration-helper.git
  1. Navigate to your app folder.
  2. Run the program with the following command:
        vue-migration-helper

All the lines in which a change is necessary will be highlighted. Once you are finished updating, or if you still have doubts, you should take a look at the official documentation migration page at https://rc.vuejs.org/guide/migration.html.

How it works...

Reading through the documentation will help you understand the critical points that need to be updated. Here I will provide you a rationale for some of the most challenging modifications.

Deprecation of $broadcast, $dispatch, and the events option

Both methods $broadcast and $dispatch are now merged in the $emit method with the same syntax as the old version. Unfortunately, replacing every instance of $broadcast and $dispatch with $emit is not guaranteed to always work because the pattern used to manage events is a little different now.

In Vue 1, you had events follow a path either downward (for $broadcast) or upward (for $dispatch), and horizontally (for $emit) through the hierarchical tree.

To be honest, I never liked having two (three if you count the old $emit) methods for emitting events. It was confusing even in the smallest contexts because you had to ask yourself is this event for parents or children? Most of the time it was not that important of a distinction, you just wanted your method to fire. But there is no such thing as a free lunch; we have to add a moving part to our system to make everything work in the new paradigm.

Now all events should pass through one or more central hubs. The role of this central hubs can be taken by a Vue instance since they implement the necessary interface.

When emitting an event consumed by v-on, you're good to go by replacing $broadcast with $emit, since the event doesn't have to travel far. On the other hand, if you are defining an interface for a component in terms of events, you will have to say goodbye to the events option since it will not work anymore. This is the direct consequence of having all the events passing through a hub--the events option wouldn't know where to register all the events. This is the trade off for having a single emitting method: it fires in every direction but only in a precise piping.

Let's say you have a dedicated empty Vue instance that will act as an event hub:

var eventBus = new Vue()

If you are writing a teapot component and you want to register the brew event, you will write in the created hook something like the following:

new Vue({ 
  el: '#app', 
  components: { 
   comp1: { 
         template: '<div/>', 
         created () { 
         eventBus.$on('brew', () => { 
         console.log('HTTP Error 418: I'm a teapot') 
        }) 
      } 
    }, 
    comp2: { 
         template: '<div/>', 
         created () { 
         eventBus.$emit('brew') 
      } 
    } 
  } 
})

And with the HTML:

<div id="app"> 
  <comp1></comp1> 
  <comp2></comp2> 
</div>

Every time the brew event is emitted with eventBus.$emit('brew'), the console will output a message.

Note

As you can see, this example is not very scalable. You cannot register a lot of events in the created hook and then expect to easily keep track of what they do and in which hub they are registered. For these more involved scenarios, the suggested way to proceed is to use Vuex, introduced in later recipes.

Any component you'll write can act as an event hub. You also have the API methods $off which deletes listeners, and $once, which listens for an event but only once.

Deprecation of array filters

If you had a lot of filtered v-for lists, I have bad news for you. Even if in the wild the most common use for filters was with v-for, the community chose to remove this feature. The reason is mainly because having a lot of filters, often piped together, was hard to reason about and thus to maintain.

The new recommended way to filter a list is with a computed property. Luckily for you, we have an entire recipe on how to do that. See the recipe Filtering a list with a computed property in the next chapter.

Deprecation of Vue.config.delimiters

Custom delimiters are not at the component level. If you want, you can have two different components using different delimiters.

This is fairly easy to upgrade and allows you to write components intended to be used inside other template engines:

<div id="app"> 
  {!msg!} 
</div>

new Vue({ 
 el: '#app', 
 data: { 
   msg:'hello world' 
 }, 
 delimiters: ['{!','!}'] 
})

Renaming of life cycle hooks

Life cycle have now a more consistent naming that will help with remembering their names in the long run:

Old hook

New hook

init

beforeCreate

created

created

beforeCompile

created

no equivalent

beforeMount

compiled

mounted

ready

mounted

attached

no equivalent

detached

no equivalent

no equivalent

beforeUpdate

no equivalent

updated

 

About the Author

  • Andrea Passaglia

    Andrea Passaglia was born in Genoa, in northern Italy. Interested about technology since his parents gave him a toy computer when he was a boy, he started studying web technologies at an early age. After obtaining his master's degree in computer engineering he worked on the design and implementation of web interfaces for companies of various sizes and in different industries (healthcare, fashion, tourism, and transport). In 2016 he moves in the silicon valley of Europe to tackle new problems in the banking industry at the Edgeverve Dublin Research and Development Labs. A backend technologist by trade, Vue.js is his first tool to bring to life his creations when it comes to the frontend. Andrea is married to a lovely Russian girl from Siberia and they often cook together mixing culinary traditions.

    Browse publications by this author

Latest Reviews

(7 reviews total)
rychlé vyřízení a skvělá spolupráce
Excellent book. A lot of examples, all of them explained in detail.
good book to understand how to use vue

Recommended For You

Book Title
Unlock this full book FREE 10 day trial
Start Free Trial