From Vue.js in Action by Erik Hanchett

This article explores how to get started with Vue.js and gives insight into some of its core workings.


Save 37% on Vue.js in Action. Just enter code fcchanchett into the discount code box at checkout at manning.com.


When building a complete web application, i.e. a webstore with product listings, a checkout process, an administrative interface and more; the completed webstore may seem like it’s a long way off, even if you’re new to web application development. Don’t fret! Vue allows us to start small, build on what we learn, and ship a sophisticated product in one smooth progression.

The key to Vue’s consistency at every stage of an applications growth is the Vue instance. A Vue application is a Vue instance, Vue components are all Vue instances, and you can extend Vue by creating instances with your own custom properties.

It’s impossible to touch on all the facets of the Vue instance in a single article, but we’ll build on the foundation we establish as we watch an application evolve. As we explore new features, we’ll often refer to what we learn about the Vue instance.

Our first application

To begin our journey, we’re going to create the foundation of a webstore application, display the name of a webstore, and create a single product listing. Our focus is on how we create a Vue application and the relationship of the data in our view-model to how it gets displayed in the view.

This is what we want our theoretical app to look like once it’s complete.


Figure 1 A preview of our humble webstore’s beginnings.


The root Vue instance

At the heart of every Vue application, no matter how big or small, is the root Vue instance. Creating a root Vue instance is done by invoking the Vue constructor, new Vue(). The constructor bootstraps our application by compiling an HTML template for our app, initializing any instance data, and creating the data and event bindings that make our application interactive.

The Vue constructor accepts a single JavaScript object, known as the options object, new Vue({ /* options go here */ }). It’s our job to populate that object with everything the Vue constructor needs to bootstrap our application, but to start off we’re going to focus on a single option, the el option.

The el option is used by Vue to specify a DOM element (hence el) where Vue mounts our application. Vue locates the corresponding DOM element in our HTML and uses it as the template for our application.

Open the chapter-02/index.html file in your text editor, which contains the code shown here in Listing 1. This code is the beginning of our webstore application. (If you haven’t downloaded the code that accompanies this article, it’s here: https://github.com/ErikCH/VuejsInActionCode).

Listing 2.1 Our first Vue application – chapter-02/index.html

  
 <html>
   <head>
     <title>Vue.js Pet Depot</title>
     <script src="js/vue-2.1.0.js"></script>             ❶
   </head>
   <body>
     <div id="app"></div>                                ❷
  
     <script type=”text/javascript”>
       var webstore = new Vue({                          ❸
         el: '#app'                                      ❹
       });                                               ❸
     </script>
   </body>
 </html>
  

❶ Include our local copy of vue.js

❷ The element where Vue mounts our application

❸ The vue constructor

❹ A CSS selector used to locate the DOM mounting point

The markup in Listing 1 contains a single div element with a CSS id selector, #app. Vue uses that value to locate our div, and mounts the application to it.

If the CSS selector we provide resolves to more than one DOM element, Vue mounts the application to the first element which is matched by the selector. For example, if we had an HTML document with three div elements, and we invoked the Vue constructor as new Vue({ el: 'div' }), Vue mounts the application at the first div element of the three.

If you needed to run multiple Vue instances on a single page, you’d mount them to different DOM elements by using unique selectors. This may seem like an odd practice, but if you use Vue to build small components, such as an image carousel or a webform, it’s easy to see how you could have several root Vue instances all running on a single page.

Making sure our application is running

Let’s head over to Chrome and open the chapter-02/index.html file right now, though it won’t yet render anything we can see in the main browser window; no visible HTML!)

Once the page loads, open the JavaScript console if it isn’t already open, and hopefully you’ll see … <drum roll> … absolutely nothing (or perhaps a note about downloading vue-devtools if you haven’t already done this).


Figure 2 The JavaScript console with, hopefully, no errors or warnings.

 

 

Vue debugging 101

  • If you see a message similar to “Failed to load resource: net::ERR_FILE_NOT_FOUND” in the console, chances are the path to vue.js is incorrect or the file can’t be found. Check the script element’s path for typos, and if you’re using a local copy of vue.js, be sure it exists and it’s in the right spot.

  • This next one is common, “Uncaught SyntaxError: Unexpected identifier.” This is almost always a typo in the JavaScript code, and can usually be traced to a missing comma or curly brace. You can click the file name and line number displayed on the right of the error to jump to the corresponding code. Keep in mind that you may have to hunt a few lines up or down to find the offending typo.

  • The last common error message looks like “[Vue warn]: Property or method "propertyname" is not defined …” This means something didn’t get defined in the options object when the instance was created. Check to see if the property or method exists in your options object, and for typos in its name if it does. Also, check to be sure the name is spelled correctly in the binding in your markup.

If you run into something you can’t figure out, or a particularly nasty error, you can check out the Help section of the Vue forum https://forum.vuejs.org/c/help or ask for help in the Vue Gitter chat https://gitter.im/vuejs/vue.

 

After Vue is finished initializing and mounting the application, it returns a reference to the root Vue instance which we stored in our webstore variable. We can use that variable to inspect our application in the JavaScript console. Let’s use it now, to make sure that our application is alive and well before continuing.

With the console open, enter webstore at the prompt. The result is a Vue object that we can inspect further in the console. For now, use the disclosure triangles (►) to expand the object and look at the properties of our root Vue instance.

You may have to scroll around a bit, but you should be able to locate the el property we specified as part of our applications options object.


Figure 3 Using the webstore variable to print a representation of the Vue instance and explore its properties.


We’ll use the console to access our instance for debugging, manipulating data and triggering behaviors in our application as it’s running, allowing us to validate that it behaves as expected.

We can also use vue-devtools to peek inside our application as it’s running. Let’s see how it compares to using the JavaScript console.


Figure 4 The vue-devtools window with nothing selected.


The vue-devtools extension provides loads of functionality for inspecting a Vue application, its data, and the relationship of its components. As an application grows in size and complexity, the searchable tree view in vue-devtools shows us the relationship of components in a way the JavaScript console can’t.

We’ll frequently use both tools to zero in on problems with applications as we build. In fact, we can use vue-devtools to discover another way to access our application instance in the JavaScript console.


Figure 5 The root instance selected in vue-devtools, with a variable dynamically assigned to the instance.


When you select an instance in the tree view, as in Figure 5, vue-devtools assigns a reference to the instance to the $vm0 variable. We can use $vm0 the same way we used our webstore variable. Try using $vm0 in the JavaScript console to see if you can inspect the root Vue instance.

 

Why do we need more than one reference?

The Vue instance assigned to the $vm0 variable reflects the current selection made in vue-devtools. When an application is made up of hundreds, or even thousands of instances, it isn’t practical to declaratively assign each instance, and having a way to access specific instances which are created programmatically becomes indispensable when inspecting and debugging such a complex application.

 

Displaying something inside our view

At the moment our application is a real snoozefest. Let’s liven it up by displaying some data from our application instance in our application’s template. Remember, our Vue instance uses the DOM element we provide as the basis for its template.

We’re going start by adding the name of our webstore. This’ll show us how to pass data into the Vue constructor, and how to bind that data to a view. Let’s update the application code from Listing 1.

Listing 2 Adding data and a data binding – chapter-02/index.html

  
 <html>
   <head>
     <title>Vue.js Pet Depot</title>
     <script src="js/vue-2.1.0.js"></script>
   </head>
   <body>
     <div id="app">
       <header>                                          
         <h1 v-text="sitename"></h1>                           </header>                                          
     </div>
  
     <script type="text/javascript">
       var webstore = new Vue({
         el: '#app', // <=== Don’t forget this comma!
         data: {                                         
           sitename: 'Vue.js Pet Depot'                  
         }                                               
       });
     </script>
   </body>
 </html>
  

 A header element’s added to the div

❷  Data binding for the sitename property

A data object is added to the Vue options

The sitename property we bind to in the header

We’ve added a data object to the options we pass into our Vue constructor. That data object contains a single property, sitename, which contains the name of our webstore.

Our site’s name needs a home, and we’ve also added a header element to the markup inside the application’s root div element. On the heading element <h1>, we use a data binding known as a text interpolation, v-text=sitename“.

A text interpolation prints a string representation of the property it references, and in this case, once our application is up and running, we should see a header with the text “Vue.js Pet Depot” displayed inside it.

If you need to display a property value in the middle of a larger string, you can use Mustache syntax—{{ property-name }}—to bind to a property. For example, if we wanted to include the name of our webstore in a sentence, we might write <p>Welcome to {{ sitename }}</p>.

Tip Vue only borrows the {{ … }} syntax from Mustache for text interpolations, not the entire Mustache specification. If you’re curious where it comes from, visit the online manual at https://mustache.github.io/mustache.5.html.

With our data binding in place, let’s go see how our new header looks in the browser.

Inspecting the sitename property

When you reload the application in Chrome, you should see the header proudly displaying the value of our sitename property.

The visual appearance of our header is provided by the stylesheet in chapter-02/app.css. If you’d like to tinker with the appearance of the header, open that file up and find the styles defined by #app > header.


Figure 6: Our sitename property displayed in the header of our webstore.


Vue automatically creates getter and setter functions for each property of the data object when it initializes our application. That means we can retrieve the current value of, or set a new value for, any of our instance’s properties without writing any additional code.

To see these functions in action, let’s start by using the getter to print the value of the sitename property.


Figure 7: Using the console and vue-devtools, we can check in on our sitename property.


As you can see in Figure 7, the getter and setter functions for our sitename property are exposed at the root level of our application instance. That lets us access the property from the JavaScript console, or any other JavaScript that interacts with our application.

You can also see the property listed in vue-devtools when we select the <root> instance. [IMAGE] show it in vue-devtools (the right half of the previous figure). Now let’s see what happens when we use the setter to set the value of sitename in the JavaScript console.


Figure 8: Using Vue’s property getter and setter to print and update the sitename property, respectively.

 

Once we provide a new value for sitename and hit enter, the output in our header element is automatically updated. This is Vue’s event loop in action. The next step would be to look at the Vue lifecycle to see how and when changes to our data trigger updates to the view, but that’s a topic for another time.


For more on Vue.js, check out the book on liveBook here and see this slide deck.