Introduction to Vue.js. The first half consists of all slides, and the second half consists of all those slides along with detailed notes.
All the sample code can be found at https://github.com/MarkFreedman/VueJS101
Mark FreedmanSoftware Engineer at LiftEngine; LorMarSoft, LLC; Weird Candle, LLC
27. Vue.js 101
Learning Resources
Vue.js:
https://vuejs.org/
Support Forum
https://forum.vuejs.org/
Job Portal
https://vuejobs.com/
My Favorite Tutorial
https://www.udemy.com/vuejs-2-the-complete-guide/learn/v4/overview
awesome-vue:
https://github.com/vuejs/awesome-vue
My Site:
https://MarkFreedman.com
This Session’s Slides and Examples
https://github.com/MarkFreedman/VueJS101
28. Vue.js 101
Will It Change Your Life?
Dev Storyteller presents:
Mark Freedman
https://MarkFreedman.com
@MarkFreedman
You can find the sample code at:
https://github.com/MarkFreedman/VueJS101
1
29. Vue.js 101
Who Am I to Speak About
Vue.js?
I’ve been developing web-based apps since
the mid 90s, with heavy JavaScript
development since 2011. Hated JavaScript
until 2007 or so. Have loved it since. Never
indifferent. I’ve been in software
development for a few decades.
2
31. Vue.js 101
Preparing for Use
vuejs.org
We can reference Vue.js in our apps either
referencing a CDN (recommended), by
downloading it, or by installing with NPM or
Nuget, etc.
We'll download for this session, to prevent
against connectivity issues.
The developer (non-minimized) version of the
library will give us extra warning and error
information.
Although not required, we'll use some simple
ES6 features today as well.
4
33. Vue.js 101
Instantiation
Main Wrapper Element
Data Object
Interpolation
(vue1.html)
We need to create a Vue instance in JavaScript. I’ll start simple by including the JavaScript in the HTML
file.
An options object is passed to the instantiation. We’ll first focus on these properties of this object:
el – Here, using CSS selectors, we specify the root “wrapper” element Vue will control.
data – This is an object where we define variables that Vue will “react” upon. We would
initialize each data item with default values here as well.
Vue uses “templates” to generate HTML. Although it may appear the HTML would be displayed as-is,
everything inside the el element is first "compiled" before it is displayed to the DOM.
In our HTML, we assign an id of “app” to the main DIV element. We could have used a CSS class here,
or even just an element without a class or id. The main thing to keep in mind is that the el value passed
to the Vue instance should hold the selector. If multiple elements for the same selector are on the page,
the first instance will be used by Vue. This is why 99.9% of the time we use an id.
Vue controls everything inside this root element. It renders output, and reacts to events on this and all
child elements.
We’re using string interpolation to allow Vue to render our title. We use curly braces (or mustaches) –
{{ }} – around an expression, similar to Angular string interpolation. Any simple JavaScript expression
can be placed here. In other words, literals, variables, operations, and anything that isn’t a JavaScript
statement, for the most part. Here, we are passing title, which Vue automatically searches for in the data
property in the options object. If we used quotes around title, the literal “title” would be rendered. But
because we used it as a variable, the current value assigned to that variable is rendered.
Vue automatically protects against unintended XSS. For example, interpolating a URL to any HTML
element will encode the URL. HTML will be treated as literal text. If we do need to render HTML, we
would use the v-html directive instead of rendering with mustaches.
6
34. Vue.js 101
Reacting to data changes
(vue2.html)
Since Vue is “reactive” (no pun intended for React users), it listens for
changes to the data properties to decide if and when to re-render. If we
go to the Developer Tools, we can change the value of the data in the
console, and Vue will re-render any place on the page that data was
rendered before.
How do we do that? How do we reference title from the console? Well,
since we instantiated Vue without assigning the reference to a variable,
we don’t have a direct way of doing so. So lets make a minor change to
the JavaScript first, and assign the instance to a variable called
“myApp”.
After refreshing the page, now we can go to the console and type
myApp.title = “My New Title”. It effectively changes the displayed title.
What’s wrong with this picture? This shouldn’t have worked, right?
There’s no title property in the Vue prototype, right? Well, this is some
Vue “magic.” Vue automagically surfaces the data property to the top
level of the instance for easy access. We’ll see more of this now…
7
35. Vue.js 101
Methods
(vue3.html)
Vue wouldn’t be very useful if we couldn’t throw logic
around our components. The “methods” property of the
options object is where we declare any methods we want
Vue to use. You can consider these methods as members
of a controller of the component. Let’s create a method
called getTitle (using ES6 syntax), and instead of
rendering title directly in the template, let’s use a call to
getTitle().
Note that in JavaScript we’re using “this” to reference the
method. Like data properties, Vue surfaces methods as
well. Like “myApp” from outside the Vue instance, we
would use “this” from inside the instance. If we look at the
console, we can confirm that the method was called by the
Vue rendering engine. How did we do that?
8
36. Vue.js 101
Vue Lifecycle
(vue3.html)
Vue wouldn’t be very useful if we couldn’t throw logic around our
components. The “methods” property of the options object is where we
declare any methods we want Vue to use. You can consider these
methods as members of a controller of the component. Let’s create a
method called getTitle (using ES6 syntax), and instead of rendering title
directly in the template, let’s use a call to getTitle().
Note that in JavaScript we’re using “this” to reference the method. Like
data properties, Vue surfaces methods as well. Like “myApp” from
outside the Vue instance, we would use “this” from inside the instance. If
we look at the console, we can confirm that the method was called by
the Vue rendering engine. How did we do that?
We hooked into the Vue lifecycle. Let’s take a look at the lifecycle
diagram. Deep diving into this is more of an advanced feature, but we’ll
just discuss a commonly used hook – created. This is automatically
called when the component has been initialized and the DOM has been
updated. We add our lifecycle hook functions to the options object. In
this case, we’ll define a created function. All we’re doing here is
displaying a message in the console for debugging purposes.
9
37. Vue.js 101
Rendering changes
Virtual DOM
As we have just seen, Vue immediately rendered
the changed title to the page. But what if we had
dozens of DOM elements on our page? Isn’t
updating the DOM inherently slow? Yes it is, but like
React, Vue actually updates an internal “virtual”
DOM before making any physical changes to the
rendered output. Once all updates are made to the
virtual DOM, Vue then does a comparison of the
virtual DOM to the actual DOM, and only updates
the differences.
Now that we got our introduction to methods, let’s
take a look at event handling in Vue…
10
38. Vue.js 101
Events
(vue4.html)
You should feel comfortable with Vue built-in directives if you’re already familiar with Angular’s. The first
one we’ll look at is the v-on directive. Vue built-in directives are prefixed with “v-”. The v-on directive is
used for handling events on the element the directive is placed into.
Let’s allow the user to change the title by clicking a button.
We’re back to the version where we’re rendering the title data item. We’ll create a method called
changeTitle(), which will simply change the value of title to another hard-coded value. Then we’ll add a
button to the HTML, and add a v-on directive. Directives such as v-on accept parameters which follow
the directive name and preceded by a colon. v-on always requires an event name (standard JavaScript
event names), so we’re going to use v-on:click here. We’ll specify “changeTitle” as the value for the v-
on directive. A parenthesis after the name is not required.
Running the app, we can see that clicking the button changes the title.
By the way, we didn’t need to create a method for this. Like with interpolation, we only need a valid
JavaScript expression. We could have simply specified the handler like this: v-on:click=“title = ‘I
changed this title’”, which does the same thing. Note that we did not have to prefix the method, nor
the data item with “this” in the HTML. Vue recognizes its directives and interpolation statements, and
understands any expression references items on the Vue instance. Since in the methods we can access
any variable in scope, we must prefix a Vue item with “this” to clarify that we’re referencing a Vue data
object’s variable.
Because v-on is such a common directive in Vue, there’s a shorthand notation that I’ll use all the time
going forward. Instead of typing v-on: before the event name, just type @ followed by the event name.
In this example, it would be @click.
11
39. Vue.js 101
Event Object Argument
(vue5.html)
Vue always passes a DOM event object to the event handler if you specify no
parameters for the function specified in the v-on directive. Just like any other
event handler in JavaScript, jQuery, etc., it contains appropriate properties
based upon the event.
Let’s look at a simple example. We’ll add another event handler to our button
for mouseover. Again, we don’t need to pass a parameter (or even
parenthesis), because Vue automatically passes an appropriate event object
to the handler. We’ll call it event but it could be called anything you like. Note
that we’re using the @ shorthand.
We’ll create another interpolated string for displaying the mouse coordinates.
We’ll have to add another data item to hold the value, so we’ll initialize it to an
empty string.
In the event handler, we’ll simply use the x and y coordinates passed via the
event object to our mouseover handler, onMouseOver.
This is cool, but what if we want to pass other values to the event handler?
What happens to the event object argument? It disappears. But don’t worry –
we can get it back…
12
40. Vue.js 101
Multiple Event Handler
Arguments
(vue6.html)
Let’s create a second button, where we can set a different
title. This time we’ll pass an argument containing the new
title.
But in addition to changing the title, we want to pop up an
alert displaying which button we clicked. Since we’re using
the same event handler to handle both buttons, how are
we going to know?
Well, in our v-on (or @) directive, we also pass in a built-in
Vue variable called $event. Built-in variables start with $ in
Vue. So now our event handler will accept two parameters;
the user-defined parameter we created, and the $event
parameter because we’re overriding the default Vue
behavior.
13
41. Vue.js 101
Unidirectional Data Binding
(vue7.html)
Instead of using a couple of buttons for pre-canned titles, let’s try an example
where we want to accept input from the user in order to change the title.
We’re using an input field with a new directive, v-bind, in order to initialize the
value of the input field to the title data property. v-bind is always followed by
a colon, and then the HTML attribute to bind to a data property. In this case,
because we’re using v-bind:value=“title”, Vue will compile the template,
binding the value held in the title data property to the value attribute. If we
didn’t precede the value attribute with v-bind:, the literal, “title”, would be
displayed instead. Don’t use the mustache syntax in the v-bind value. Vue
already knows it’s an expression and not a literal.
In order to capture our input and update the title on the page, we’ll need to tell
Vue to react to the change of the input. Like we learned earlier, we simply add
the @change directive (in other words, v-on:change) to handle the change to
the input. We’ll create an onChange handler method to update the title on the
page.
This is great, but it’s so common Vue has a shortcut two-way binding option
for this behavior…
14
42. Vue.js 101
Two-Way Data Binding
(vue8.html)
Sometimes two-way binding is considered a “bad” thing (see AngularJS 1.x). But it’s
fine in Vue, because it’s only valid within the same component. You’ll still be using
one-way data flow between components. Let’s change the prior example to use
two-way binding instead of event handling.
Similar to Angular, all you need is to use the v-model directive to wire up two-way
binding. By specifying a property in the data object, Vue will automatically link up
both the input and output.
Let’s update the input text field from the prior example. Now, by replacing the v-bind
directive with v-model, and setting it to “title”, we’re now binding the input field to
the displayed and styled title.
(vue9.html)
When we run the page and modify the text field, we see the displayed title updated in
real time. By default, this binding is on key press. If you want to retain the old way of
only reacting on the loss of focus, we can add a modifier to the v-model directive: v-
model.lazy. There are several built-in modifiers for Vue directives. The .lazy modifier
changes the behavior of the event handling to the change event instead of the
keypress event.
15
43. Vue.js 101
More Advanced Example
(music-playlist-builder-1)
At this point, we’ll look at a more involved application to learn some more interesting features.
We’ll create an index.html file as the entry point for our site. We’ll also create subdirectories
for CSS, JavaScript, and assets (an input file, in our example).
We’ll be making use of Bootstrap to style our app. We’ll also add another CSS file with a few
simple styles.
We’ll also break our application into multiple JavaScript files, since we’re going to start using
custom components, and keeping them separate from each other makes everything a lot
cleaner. In a larger application, we’d make use of what is called “Single File Components,”
which is more of a standard way of creating independent components in .vue files. But this
is a more intermediate topic which we may not have time to cover in this intro.
Let’s take a look at our root JavaScript file, main.js. Like we did in our other examples, this is
where we instantiate our main Vue object.
We’re also making use of a Vue plugin called vue-resource. This is a “promise” library we’ll be
using to load a data file from the server. In Vue, in order to use plugins, we load them via
the Vue.use function. Of course, don’t forget to include the JavaScript file when making
use of plugins. We won’t cover this plugin in detail, as it’s beyond the focus of this session.
16
44. Vue.js 101
Components
We’ll dive into this more in a bit, but let’s take another look at the index.html file. Note that in the root Vue element
(id=“app”) we have an element called <app>. There is nothing significant about this name, except for the fact
that you’ll notice it’s not a standard HTML element. It’s actually a custom Vue element.
Let’s look at the app.js file. This file consists of a single JavaScript statement; a call to Vue.component. This is how
we use JavaScript to create a custom component that we can place anywhere in our HTML nested somewhere
within the element we map to Vue via the el property.
The component function takes two parameters. The first parameter is the name of the component. If you are familiar
with Angular, Vue also automatically converts camelCase references in JavaScript to kebab-case when used in
HTML. Although it doesn’t matter here, since we’re just calling this component “app,” if we called it something
like “myApp,” in the HTML, we’d call it <my-app>.
The second parameter contains an option object, just like we pass when creating the main Vue instance. Let’s go
through each property in this object.
The template property contains the HTML rendered when Vue finds the component on a page. Remember, like I
mentioned earlier, this isn’t really HTML, but is an HTML template that Vue “compiles” and renders in the virtual
DOM before inserting into the actual DOM, because it still has to go through all the other Vue directives and
string interpolation.
The data property is very similar to the data property for the main Vue instance, with one significant difference – in
components, we need to return the data object, so every property is wrapped in a return statement. All the data
properties here are instance properties of the component. In other words, if you have multiple instances of this
element through your web page, each will get its own copy of the data properties. Likewise, all these properties
are local to the component instance.
The methods property works the same as for the main Vue instance, except that the methods defined here are local
to the component.
We also have a created method for displaying a message to the console when the object is instantiated.
17
45. Vue.js 101
List Processing
v-for
Often, we need to generate multiple instances of HTML elements when building lists or other repeatable
patterns. In Vue, we use the v-for directive.
Let’s take a look at the app component again. We’re creating a music playlist builder, so we’ll obviously
be rendering lists of songs. Take a look at the first <li> element. We’re using a v-for directive to
loop through the tracks array we declared in the data property of our options object. When we want
to loop through an array, the first parameter of the v-for statement is often the array item, followed
by the in keyword and then the array name. But if we want to get access to the array index and use
it within the loop, the first parameter is a pair of variables – the item followed by the index. For this,
we will need the index at a later point, so we’re specifying it here.
Let’s run the app. I’m using a Visual Studio Code plugin that quickly spins up a server for us. We’ll need
to run this page in a server because of XSS restrictions on loading data. Note that there is no list
displayed, because we don’t have any data yet. We rendered a button for loading tracks from an
external source. In case we don’t have good Internet connectivity, I created a local JSON file in the
assets folder. I got this data from the last.fm site. They have useful APIs if you’re a music fan.
This is an intro course, so I’m not going to get too much into the promise library call we’re making to
load the data, but let’s look at the button in the template. In addition to the hard-coded classes, we
have the familiar @click directive to specify our event handler (loadAllTracks) for the click event.
The most important line to look at is where we’re assigning the result to tracks array. When this
happens, since tracks is a Vue data property, Vue will automatically react to it changing. Vue
renders the change in the virtual DOM, and then compares the virtual DOM to the actual DOM. The
only difference it will find is to the <li> items in our v-for list, so only that part of the DOM will be
updated, and the rest of the DOM will remain untouched.
Let’s click the button to make this happen, and then let’s inspect using the Developer Tools. Note that
Vue rendered multiple <li> elements due to the v-for loop we created in our template.
18
46. Vue.js 101
Array Gotchas
I need to take a moment to explain an
idiosyncrasy of Vue. If we change an existing
element in an array, Vue will NOT see and
react to that change. It has no problem when
adding or removing items from an array, but
not when modifying an existing element. Vue
does provide a built-in function for setting the
value of an element that it will react to: arr.
$set(index, value). This is simply syntactic sugar
for arr.splice(index, 1, value), which
removes, then re-adds an element, basically
tricking Vue into seeing the change.
19
47. Vue.js 101
Dynamic Classes
:class
Let’s take a closer look at the first <li> template declaration. In addition to the hard-coded class of
Bootstrap’s list-group-item, there is the :class declaration (a colon (:) being a shortcut for v-bind:
since it’s used so often). This is where we can dynamically specify classes based upon
expressions. In this case, we’re setting the class based on the value of track.class. The class
parameter is not part of the downloaded track data, but we add it on the @click event.
Let’s take a look at the handler for the @click event, addTrack(). We’re passing three of our own
parameters to the handler, along explicitly with the $event object, as discussed earlier. We can see
here why we are capturing the index in our v-for loop. We need the index in order to know which
element we just clicked so we can mark it as selected. We’re also passing in the artist name and
track title in order to add an item to the selectedTracks array used in the second defined <li>
element. Yes, we could have passed in track[index] to save on a parameter as well. We’re also
using the class property of the track as a flag to see if the track has already been selected. In
addition to pushing the track to the selectedTracks array, we’re setting the class to “active”, which
allows Bootstrap to highlight the selected track via the :class binding attribute. We’re also setting a
modified flag that we’re making use of in a couple of other attributes in our template that we’re
about to learn about.
A bit more on the class binding attribute first, though. We are using it to bind to a string value to
explicitly set the class. First, note that any classes specified here is in addition to any hard-coded
classes added to the class attribute. Second, we can also pass in an object containing a collection
of class/value pairs. We could have used :class="{ active: isActive }” instead, and if
isActive is set to true, the “active” class would be applied. This is an especially useful option if we
were dynamically manipulating multiple classes on an element.
Let’s now look at how the modified flag is being used…
20
48. Vue.js 101
v-if
v-show
Often, we need to conditionally create or display a DOM element. Vue
gives us a couple of helpful directives for this: v-if (and the
corresponding v-else) and v-show.
We’re using the modified flag to decide whether or not to display an
asterisk above the selected tracks list indicating a “dirty” flag
(unsaved changes were made to the list). In this situation, the
element is always created in the DOM, but v-show simply decides on
whether or not the element will be displayed. Effectively, it is setting
the display style to “none” or “default”.
We’re making use of v-if to decide whether or not to even render the
“Save Playlist” button at all. When would you use one over the other?
A good rule of thumb is to use v-show if the element display will often
be toggled, but use v-if the rendering of the element is not likely to
change during the session.
v-if also has corresponding v-else and v-else-if directives, which must
immediately follow the v-if, and are pretty self-explanatory.
21
49. Vue.js 101
Dynamic Styles
:style
Note that we’re also making use of the :style directive to
modify the style of the page title based on the modified
state of the data. As with the alternative syntax
for :class, we pass in an object containing a collection
of style/value pairs. We make use of the camelCase
version of style names, which Vue converts to the
standard kebab-style format when rendering the
elements to the DOM. If we wrapped the style in quotes,
we could have used ‘background-color’ instead of
backgroundColor.
For both :class and :style, we could use arrays of classes
and styles, respectively, as well.
Vue will also create style prefixes for each browser type
from the styles you specify dynamically.
22
50. Vue.js 101
Custom Filters
(music-playlist-builder-2)
Like Angular, Vue supports filters when rendering.
The difference is, there are no built-in filters in
Vue. But they are simple to build.
I know this example is derivative, but let’s build a
filter that transforms the artist name before
displaying it in the list. Our filter will wrap the first
character of the name with brackets.
Filters can be used in mustache interpolation and in
v-bind expressions, and can be piped through
other filters.
23
51. Vue.js 101
Custom Components
Props
(music-playlist-builder-3)
Right now, we have a single component containing our entire template. In a larger application, we’d break this down
into separate components. There are some key benefits: 1) it makes it a lot cleaner, 2) it encapsulates everything
pertaining to a specific portion of the template, and 3) it allows for easy reuse.
Let’s create and use a separate component for the Save button and the related modified indicator. We’ll create a
new JavaScript file called save-tracks.js. Don’t forget to add the JavaScript file reference to index.html.
Within the component, we’ll have the normal options object that defines the template and supporting data and
methods. We’ll name the component “saveTracks.” Remember that Vue will treat this as “save-tracks” when used
in a template. We can also move the supporting savePlaylist() function to this component, since it’s just there to
support the functionality of this component. But how do we pass the modified state to this component, since the flag
is based on data properties of the parent component, app?
We make use of another option object property called props. This is an array of string values representing attributes
passed to the component. The component looks for an expression assigned to that attribute, and applies it to an
internal variable by that name (in this case, modified).
We can now replace the <h2> and <button> elements in the main app component with this new <save-tracks>
elements. Note that we’re binding the attribute modified (because it’s preceded by a colon or v-bind:) to an
expression. The component captures the result and places it into the modified prop, where we can use it to control
logic in the component and template.
This is one-way data flow. Although we won’t cover it today, in order to communicate back to the parent or other
sibling components, we’d raise custom events from the child component to keep the components loosely coupled.
Also, note that components cannot be composed out of multiple elements at the root level. There must always be a
container element. We can simply use a <div> in many cases, but we don’t need to here, because the <h2> element
is our container for this component.
24
52. Vue.js 101
Do we love Vue.js?
Will it change your life?
Next steps.
25
53. Vue.js 101
Advanced Topics for Future Sessions?
Modifiers
Slots
Single File Components (.vue files)
Transitions and Animations
Custom Events
v-once
keep-alive
Mixins
Custom Directives
Plugins
vuex
vue-resource
vue-router
Modifiers: dot-separated values to pass to event name. A common one is "stop" for stopPropagation. Also have
"prevent" for preventDefault. Modifiers can be chained.
Key modifiers for keyboard events. For example .enter for checking if the enter key was pressed.
Computed properties are just referenced as pointers. The difference between computed and methods is methods
always are re-evaluated. Computed are only re-evaluated if any data it contains has changed. More efficient.
Could use "watch" object instead of "computed." Computed is more optimized, though. The watch properties need to
be named the same as the data being watched for changes. Computed methods are run synchronously. So use
watch when you need to check for changed properties asynchronously. For example, setTimeout or setInterval
functions. When specifying callback functions in watch methods, we lose direct access to "this," so first assign
"this" to a variable (normally called "vm") before defining the callback. Then you can reference this variable (vm)
inside the closure.
You can also take advantage of <template> to repeat multiple elements: v-for="value in valueObjects" or v-
for="(value, key) in valueObjects". You can even access the index : v-for="(value, key, index) in valueObjects"
You can also loop through numbers: v=for="n in 100"
You can use the :key binding option to track and specify the key in an array or collection of objects, so if either
changes, Vue keeps track of the position and value change, and will update the UI appropriately.
Installing the Vue CLI
npm install -g vue-cli
vue init web pack-simple projectName
cd projectName
npm install
npm run dev
26
54. Vue.js 101
Learning Resources
Vue.js:
https://vuejs.org/
Support Forum
https://forum.vuejs.org/
Job Portal
https://vuejobs.com/
My Favorite Tutorial
https://www.udemy.com/vuejs-2-the-complete-guide/learn/v4/overview
awesome-vue:
https://github.com/vuejs/awesome-vue
My Site:
https://MarkFreedman.com
This Session’s Slides and Examples
https://github.com/MarkFreedman/VueJS101
27