Getting up and Running with the Vue.js 2.0 Framework

SitePoint by Jack Franklin // Monday, April 15, 2019
Vue.js logo

This article was updated in November 2018, primarily to bring the tooling section up to date.

As soon as the popular JavaScript framework Vue.js released v2, I was eager to give it a spin and see what it’s like to work with. As someone who’s pretty familiar with Angular and React, I was looking forward to seeing the similarities and differences between them and Vue.

Vue 2 sports excellent performance stats, a relatively small payload (the bundled runtime version of Vue weighs in at 30KB 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 some later articles where we’ll look more closely at various libraries that couple nicely with the core framework.

Inspiration from Other Libraries

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’s, but its components and component lifecycle methods are closer to React’s (and Angular’s, 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.

Components, Components, Components

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.

A Vue file looks like so:

<template>
  <p>This is my HTML for my component</p>
</template>

<script>
  export default {
    // all code for my component goes here
  }
</script>

<style scoped>
  /* CSS here
   * by including `scoped`, we ensure that all CSS
   * is scoped to this component!
   */
</style>

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.

Setting Up a Project

Whilst the excellent Vue CLI exists to make setting up a full project easy, when starting out with a new library I like to do it all from scratch so I get more of an understanding of the tools.

These days, webpack is my preferred build tool of choice, and we can couple that with the vue-loader plugin to support the Vue.js component format that I mentioned previously. We’ll also need Babel and the env preset, so we can write all our code using modern JavaScript syntax, as well as the webpack-dev-server, which will update the browser when it detects a file change.

Let’s initialize a project and install the dependencies:

mkdir vue2-demo-project
cd vue2-demo-project
npm init -y
npm i vue
npm i webpack webpack-cli @babel/core @babel/preset-env babel-loader vue-loader vue-template-compiler webpack-dev-server html-webpack-plugin --save-dev

Then create the initial folders and files:

mkdir src
touch webpack.config.js src/index.html src/index.js

The project structure should look like this:

.
├── package.json
├── package-lock.json
├── src
│   ├── index.html
│   └── index.js
└── webpack.config.js

Now let’s set up the webpack configuration. This boils down to the following:

  • Tell webpack to use the vue-loader for any .vue files
  • Tell webpack to use Babel and the env preset for any .js files
  • Tell webpack to generate an HTML file for the dev-server to serve, using src/index.html as a template:
//webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const HtmlWebPackPlugin = require("html-webpack-plugin")

module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
    new HtmlWebPackPlugin({
      template: "./src/index.html"
    })
  ]
}

Finally, we’ll add some content to the HTML file and we’re ready to go!

<!-- src/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <title>My Vue App</title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

We create an empty div with the ID of app, as this is the element that we’re going to place our Vue application in. I always prefer to use a div, rather than just the body element, as that lets me have control over the rest of the page.

Writing Our First Vue.js App

We’re going to stay true to every programming tutorial ever and write a Vue application that puts “Hello, World!” onto the screen before we dive into something a bit more complicated.

Each Vue app is created by importing the library and then instantiating a new Vue instance:

import Vue from 'vue'

const vm = new Vue({
  el: '#app',
})

We give Vue an element to render onto the page, and with that, we’ve created a Vue application! We pass a selector for the element that we want Vue to replace with our application. This means when Vue runs it will take the div#app that we created and replace it with our application.

The reason we use the variable name vm is because it stands for “View Model”. Although not strictly associated with the “Model View View-Model” (MVVM) pattern, Vue was inspired in part by it, and the convention of using the variable name vm for Vue applications has stuck. Of course, you can call the variable whatever you’d like!

So far, our application isn’t doing anything, though, so let’s create our first component, App.vue, that will actually render something onto the page.

Vue doesn’t dictate how your application is structured, so this one is up to you. I ended up creating one folder per component, in this case App (I like the capital letter, signifying a component), with three files in it:

  • index.vue
  • script.js
  • style.css
mkdir src/App
touch src/App/{index.vue,script.js,style.css}

The file structure should now be:

.
├── package.json
├── package-lock.json
├── src
│   ├── App
│   │   ├── index.vue
│   │   ├── srcipt.js
│   │   └── style.css
│   ├── index.html
│   └── index.js
└── webpack.config.js

App/index.vue defines the template, then imports the other files. This is in keeping with the structure recommended in the What About Separation of Concerns? section of Vue’s docs.

<!-- src/App/index.vue -->
<template>
  <p>Hello, World!</p>
</template>
<script src="./script.js"></script>
<style scoped src="./style.css"></style>

I like calling it index.vue, but you might want to call it app.vue too so it’s easier to search for. I prefer importing App/index.vue in my code versus App/app.vue, but again you might disagree, so feel free to pick whatever you and your team like best.

For now, our template is just <p>Hello, World!</p>, and I’ll leave the CSS file blank. The main work goes into script.js, which looks like so:

export default {
  name: 'App',
  data() {
    return {}
  },
}

Doing this creates a component which we’ll give the name App, primarily for debugging purposes, which I’ll come to later, and then defines the data that this component has and is responsible for. For now, we don’t have any data, so we can just tell Vue that by returning an empty object. Later on, we’ll see an example of a component using data.

Now we can head back into src/index.js and tell the Vue instance to render our App component:

import Vue from 'vue'

import AppComponent from './App/index.vue'

const vm = new Vue({
  el: '#app',
  components: {
    app: AppComponent,
  },
  render: h => h('app'),
})

Firstly, we import the component, trusting webpack and the vue-loader to take care of parsing it. We then declare the component. This is an important step: by default, Vue components are not globally available. Each component must have a list of all the components they’re going to use, and the tag that it will be mapped to. In this case, because we register our component like so:

components: {
  app: AppComponent,
}

This means that in our templates we’ll be able to use the app element to refer to our component.

Finally, we define the render function. This function is called with a helper — commonly referred to as h — that’s able to create elements. It’s not too dissimilar to the React.createElement function that React uses. In this case, we give it the string 'app', because the component we want to render is registered as having the tag app.

More often than not (and for the rest of this tutorial) we won’t use the render function on other components, because we’ll define HTML templates. But the Vue.js guide to the render function is worth a read if you’d like more information.

Once we’ve done that, the final step is to create an npm script in package.json:

"scripts": {
  "start": "webpack-dev-server --mode development --open"
},

Now, run npm run start. Your default browser should open at http://localhost:8080/ and you should see “Hello, World!” on the screen.

Try editing src/index.vue to change the message to something else. If all has gone correctly, webpack-dev-server should refresh the page to reflect your changes.

Yay! We’re up and running with Vue.js.

The post Getting up and Running with the Vue.js 2.0 Framework appeared first on SitePoint.

  Previous Article