Yanis Triandaphilov lives and works in Prague. He's been into Ruby and JavaScript development for more than six years now. "Being not too smart, I struggle for clarity and simplicity in everything I do."

Give Codeship’s CI/CD Platform a Try

Want to learn more?

Vue.js fascinates me. The author is Evan You, a former Angular developer. Somehow he managed to take the best of the two worlds — Angular and React — and build a simple, easy to learn, and extremely productive framework.

To show you the benefits of using Vue.js, I thought I’d make something useful from the ground up. I decided to go for apps like SimpleNote; clean and straightforward apps for taking notes. And the core part seems to be small enough to implement in a day. Then I decided to be even more down-to-earth and build a Chrome extension that will replace the new tab page with the notes app.

Setting Up the Scene

All right, that’s a start. Now we need to set up webpack and babel because we want to use ES6 features and make sure they are properly transpiled to ES5, which is better understood by major browsers.

We will also need a special vue-loader that deals with Vue’s single file components (more on it later). We will also install a bunch of other dependencies, but don’t worry. I’ll explain why we need each one.

We will also need the webpack.config.js. You can find it here. Download it and place in the root of your project. The essential part of every webpack config is the rules section, in which you define how different files should be processed.

You can now try to run yarn start. It should start up webpack and start complaining that there’s no src/index.js file. We’ll fix this later. But first, let’s take a closer look at what we are going to deal with.

Vue.js Overview

As a long-time Angular 1 developer, I find Vue.js fascinating. We all know these Angular drawbacks: steep learning curve, confusing dependency injection system (which gets even worse with ES6 modules), overcomplicated directives/components, and a huge set of docs.

Vue.js managed to keep the Angular productivity spirit, but keep things simple. It is much easier to learn, component-oriented, and faster, too, because it’s not using the dirty-checking thing. Instead, it employs the virtual DOM, much like React does. So it’s productive from Day One.

Vue.js encourages the use of components from the start. Here’s how a typical component might look:

Let’s pause there and talk a little bit. As I said earlier, Vue.js kind of takes all the good things from Angular and React. It means that it still supports the two-way binding, and every Angular developer will find it very familiar. But the way it works underneath is not the same.

There’s no dirty-checking. So how does Vue track the changes and know when to update the view? Well, it utilizes getters and setters. When you pass a data object to Vue, it walks through its properties and converts them to getter/setters using Object.defineProperty. Getters and setters are ES5-only, which is why Vue doesn’t support IE8 and below (well, who cares, right?).

Another caveat that follows from that is that you always need to specify properties that you will use in a data object, even though they are undefined at the start.

Building a Chrome Extension

Chrome extensions are easy. They just regular HTML + JavaScript web pages with access to some Chrome APIs. We’ll need a manifest file to glue it all together. Create src/manifest.json and add to it:

Note that a component is described in a file with extension .vue and it has markup (HTML), JavaScript code and CSS stylings all in one file. In Vue terminology, this is called Single File Components. While this approach is not without its flaws, it makes a lot of sense to me, since all those are essential parts of a component and they are very coupled together. So it’s only logical to keep them in one file.

On the dark side of things, this file can get very large, and your editor (Vim in my case) can blow up or start working veeeeeery slowly.

In order for webpack to be able to process single file components, we need to include vue-loader (see the previous section).

Now open Chrome. Go to chrome://extensions/. Make sure that Developer Mode is turned on. And then Load unpacked extension. Specify the dist directory. Now your extension is loaded, and you should see “Hello World” when you open a new tab.

Displaying the List of Notes

All right, that’s a great start. Let’s move on and make something interesting.

If you never saw an app like SimpleNotes, it’s very intuitive. You have a sidebar on the left with the list of all your notes, and then the central area is an editor. You can switch the current note by clicking on it in the sidebar, and then edit it in the editor. Our editor will be able to use markdown. But let’s start with a sidebar.

Oh well. A lot of stuff going on here. Let’s got through it line by line.

Note that we’re using Milligram here to split our screen into two parts. Classes like row, column, column-20, etc. are all part of Milligram’s grid API which allows us to quickly markup our grid. Of course we need to install it first:

yarn add milligram

Now, to Vue-specific things:

@click directive is a shortcut for v-on:click. It binds the DOM click event to a method in your component (we’ll get to that later). We use it twice in this snippet: first, to add a new note, and second, to set the active one.

v-for iterates over an array of things, in this case, notes. We also provide a :key directive for it to be able to differentiate between the notes.

{{ note.body }} is a common one-way binding syntax. Again it’s very similar to Angular 1.

Finally, v-model creates two-way data bindings on a form input and textarea elements.

Now all these should be very intuitive to Angular 1 users. I guess that’s why I got so easily hooked in the first place.

Here we define our data object and our methods. Note that in methods we can refer to this, which contains both data and methods. So if we want to add a new note, we do this.notes.unshift({ id: guid(), body: '# ' });. Changes are immediately displayed in the view.

You can try it yourself. Reload the browser and click on “+” to add a note.

Storing Data

We can add notes. That’s nice. But how can we save stuff so that when you open a new tab, all your notes are still there? Chrome storage to the rescue!

Chrome storage is very similar to localStorage with several differences. The most important is that we can use storage.sync API and have all our data synchronized across every browser user have. Let’s add a save function that’s going to save all our notes into storage.

Just in case this ({ [SKEY]: list = [] }) drives you crazy, this is a new ES6 destructuring syntax. It says that whatever we get, we expect it to be an object and take the value by the key SKEY and put it into list variable. And if it’s not there, set an empty array. I know it might not seem readable the first time, but it’s a very expressive language syntax that saves several lines of code.

Reload your page. Now you should be able to add notes and they will be there every time you reload or open a new tab. But if you edit an existing note, these changes won’t be saved. This is because we need to set up a watcher.

Vue watchers provide a way to track changes in data and react to it somehow. In our case, we want to save notes every time the body of a selected note is changed. Here’s how we do it.

Update the page. Now you can type anything and it will be immediately stored in Chrome. Open a new tab, reload the browser, and it will still be there.

!Sign up for a free Codeship Account

Markdown Editor

I wanted to be able to edit my notes in markdown just because I like it so much. But also because it is such a perfect way to demonstrate how can we integrate a third-party JavaScript library into Vue ecosystem. We will use simplemde, so install it with yarn.

yarn add simplemde

Then guess what? We’re going to make a component! Here’s how it will be used:

Every time the content of the editor changes, we are signaling that the model is changed with $emit function. These two attributes are a kind of interface for v-model. So every time you want your component to support v-model, you need both of these things. They are the key.

We also need to register this new component. I prefer to do it in the index.js file:

This is all we need. So now we have a fully functional notes manager, which works perfectly well in a browser. But there’s still one thing that I want to talk about.

Transitions

We’ve come to the understanding that proper transitions and animations are an essential part of any decent website. Vue gets it perfectly right and the documentation talks in detail about specifics and best practices. Let’s see how we can make the selected note appear and slide down from the top. Turns out this is very easy.

Vue provides a component called transition. So all we need to do is to wrap our element with it.

Subscribe via Email

Over 60,000 people from companies like Netflix, Apple, Spotify and O'Reilly are reading our articles. Subscribe to receive a weekly newsletter with articles around Continuous Integration, Docker, and software development best practices.

We promise that we won't spam you. You can unsubscribe any time.

Join the Discussion

Leave us some comments on what you think about this topic or if you like to add something.