A Beginner's Intro to Vue.js 2.0
Vue.js represents a progressive JavaScript framework used for building user interface. The core library focuses heavily on the ViewModel and can be used for building powerful single-page web apps.
Vue.js 2.0 sports excellent performance stats, a relatively small payload (the bundled runtime version of Vue weighs in at 16kb once minified and gzipped), along with updates to companion libraries like vue-router and vuex, the state management library for Vue. There’s far too much to cover in just one article, but keep an eye out for a later article where we’ll look more closely at some of the libraries that couple nicely with the core framework.
As we go through this tutorial you’ll see many features that Vue has that are clearly inspired by other frameworks. This is a good thing; it’s great to see new frameworks take some ideas from other libraries and improve on them. In particular, you’ll see Vue’s templating is very close to Angular, but its components and component lifecycle methods are closer to React (and Angular 2, as well).
One such example of this is that, much like React and nearly every framework in JavaScript land today, Vue uses the idea of a virtual DOM to keep rendering efficient. Vue uses a fork of snabbdom, one of the more popular virtual DOM libraries. The Vue site includes documentation on its Virtual DOM rendering, but as a user all you need to know is that Vue is very good at keeping your rendering fast (in fact, it performs better than React in many cases), meaning you can rest assured you’re building on a solid platform.
Much like other frameworks these days, Vue’s core building block is the component. Your application should be a series of components that build on top of each other to produce the final application. Vue.js goes one step further by suggesting (although not enforcing) that you define your components in a single .vue file, which can then be parsed by build tools (we’ll come onto those shortly). Given that the aim of this article is to fully explore Vue and what it feels like to work with, I’m going to use this convention for my application.
Alternatively, you can give each element a src attribute and point to a separate HTML, JS or CSS file respectively if you don’t like having all parts of the component in one file.
Example:
$ vue init webpack-simple my-sample
$ cd my-sample
$ npm install
$ npm run dev
Current available templates include:
- webpack - A full-featured Webpack + vue-loader setup with hot reload, linting, testing & css extraction.
- webpack-simple - A simple Webpack + vue-loader setup for quick prototyping.
- browserify - A full-featured Browserify + vueify setup with hot-reload, linting & unit testing.
- browserify-simple - A simple Browserify + vueify setup for quick prototyping.
- pwa - PWA template for vue-cli based on the webpack template
- simple - The simplest possible Vue setup in a single HTML file
Before we dive into a slightly more complicated app with Vue, now is a good time to mention that you should definitely get the Vue Devtools installed. These sit within the Chrome developer tools and give you a great way to look through your app and all the properties being passed round, state that each component has, and so on.
See the Pen simple-vue-app by Dan Ichim (@danichim) on CodePen.
Let’s change our view so that it contains an input element whose v-model points to the name property:
See the Pen input rendering reactive by Dan Ichim (@danichim) on CodePen.
A filter is a function you can use inside a directive or a mustache-style binding. A filter is always preceded by a pipe symbol (|). For example, if you want to display the name property in uppercase, your mustache-style binding would look like this:
{{ name | uppercase }}
See the Pen input filters reactive by Dan Ichim (@danichim) on CodePen.
The filters lowercase and capitalize can be used in a similar manner. We’ll talk more about filters in the next section.
If your model has an array, you can display the contents of that array by adding a v-for directive to a list’s < li > element. To demonstrate that, let’s add an array to our model:
The following code shows you how to display the name property of every object in the friends array:
To change the order in which the elements are listed, use the orderBy filter inside the v-for directive. For example, if you want to order the elements by age, your code should be as follows:
You can also render items conditionally. To achieve this task, use the filterBy filter. For example, the following example shows how to render only those items which contain the character “a” in the name field:
This third demo uses a two-way data binding and a filterBy filter to simulate a search:
See the Pen list filters reactive by Dan Ichim (@danichim) on CodePen.
In Vue.js, if you need to handle events associated with your view, you should add event handlers inside the view-model’s methods property. Inside all Vue.js event handlers, you can use this to access the items in the data model.
The following view-model contains a click handler:
To associate an event handler defined in the view-model with one or more UI elements in the view, you should use the v-on directive. For example, the following view has a < button > which uses the v-on directive to call myClickEvent:
Putting these snippets together, results in this demo for click handler:
See the Pen Events Handling Vue by Dan Ichim (@danichim) on CodePen.
As an example application, we’re going to be using the GitHub API to build an application that lets us enter a username and see some GitHub stats about that user. I’ve picked the Github API here as it’s familiar to most people, usable without authenticating, and gives us a fair amount of information.
Before starting an application I like to have a quick think about what components we’ll need, and I’m thinking that our App component will render two further components: GithubOutput and GithubUserData which will show the user’s information on the screen. We’ll start with the input in App.vue
App.vue will need to do two things:
- Keep track of the current value of the input
- Communicate that the value has changed, so that other components can know and therefore update their state.
There are two important attributes that you’ll notice: v-on
and v-model
.
v-on
is how we bind to DOM events in Vue and call a function. For example, <p v-on:click="foo">Click me!</p>
would call the component’s foo
method every time the paragraph was clicked. If you’d like to go through event handling in greater detail, I highly recommend the Vue documentation on event handling.
v-model
creates a two-way data binding between a form input and a piece of data. Behind the scenes, v-model
is effectively listening for event changes on the form input and updating the data in the Vue component to match.
Taking our template above into consideration, here’s how we’re using v-on and v-model to deal with the data in the form:
v-on:submit.prevent
binds run when the form is submitted. By adding .prevent that means that Vue will automatically prevent the default action from occurring (if Vue didn’t do this we could call event.preventDefault() in our code, but we might as well take advantage of Vue’s feature).v-model:username
binds the input’s value to variable username, in our code. For those of you who are familiar with Angular you may recognize this as very similar to ng-model. We declared that it had a piece of data, username, and here we’ve bound that piece of data to the input field. The two will automatically be kept in sync.v-on:click
or@click
call the method onSubmit
Now, back in our components JavaScript, we can declare the onSubmit method. Note that the name here is entirely arbitrary – you can choose whatever you’d like – but I like to stick with the convention of naming the function after the event that will trigger it.
We can refer to data directly on this, so this.username will give us the latest value of the text box. If it’s not empty, we want to let other components know that the data has changed. For this, we’ll use a message bus. These are objects that components can emit events on and listen to other events. When your application grows larger you might want to look into a more structured approach, such as Vuex. For now, a message bus does the job.
The great news is that we can use an empty Vue instance as a message bus, as recommended in the Vue docs. We’ll create src/bus.js which simply creates a Vue instance and exports it:
In App.vue we can then import that module and use it by emitting an event when the username changes.
With that our form is done, and we’re ready to start doing something with the resulting data.
We’ll create the GithubOutput component, we also import the bus module, as we’ll need it to know when the username changes. The data that this component will be responsible for will be an object that maps GitHub usernames to the data we got from the GitHub API. This means we won’t have to make the request to the API every single time; if we’ve already fetched the data previously we can simply reuse it. We’ll also store the last username we were given, so we know what data to display on the screen.
When the component is created we want to listen for any new-username events that are emitted on the message bus. Thankfully, Vue supports a number of lifecycle hooks, including the create lifecycle. Because we’re responsible developers let’s also stop listening for events when the component is not used by calling the destroyed event:
If we don’t have a username, like, when the component is first created, we want to show a message to the user. Vue has a number of conditional rendering techniques, but the easiest is the v-if directive, which takes a condition and will only render the element if it exists. It also can be paired with v-else :
Once again, this will look very familiar to any Angular developers. We use double equals rather than triple equals here because we want the conditional to be true not only if current username is null but also if it’s undefined, and null == undefined is true.
Vue.js doesn’t ship with a built-in HTTP library, and for good reason. These days the fetch API ships natively in many browsers (although at the time of writing, not IE11, Safari or iOS Safari). For the sake of this tutorial, I’m not going to use a polyfill, but you can easily polyfill the API in browsers if you need to. If you don’t like the fetch API there are many third party libraries for HTTP and the one mentioned in the Vue docs is Axios.
To make the HTTP request we’ll give the component another method, fetchGithubData, that makes a request to the GitHub API and stores the result. It will also first check to see if we already fetched the data for this user, and not make the request if so:
We then finally just need to trigger this method when the username changes:
Component GithubUserData.Vue then import in GithubOutput.vue and put the template
With that, our Vue.js 2 GitHub application is in a pretty good state! You can find all the code on GitHub.
If you’ve enjoyed this post and would like to learn more, the best place to start is definitely the official Vue.js site. If you’re interested in some of the other Vue libraries – including Vuex for state management and the Vue router keep an eye on our blog.
You’re encouraged to break your system down into small components and all in all I found it a very seamless experience. I also can’t commend the Vue team highly enough for their documentation, it’s absolutely brilliant. The guides are excellent and the API reference is thorough and yet easy to navigate to find exactly what you’re looking ( searching ) for.
I had high hopes when i started with Vue.js, as I’d heard only good things, and I’m happy to say it really met my expectations. Working with Vue feels like taking the best parts of React and merging them with the best parts of Angular. Some of the directives (like v-if, v-else, v-model and so on) are really easy to get started with (and easier to immediately understand than doing conditionals in React’s JSX syntax), but Vue’s component system feels very similar to React’s.
More to learn here: https://www.sitepoint.com; https://github.com/vuejs/vue