![]() |
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.
-
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 thescript
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.
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.
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.