Year-End Discount: 10% OFF 1-year and 20% OFF 2-year subscriptions!

Home/Blog/Vue.js Tutorial: build a functional SPA from scratch

Vue.js Tutorial: build a functional SPA from scratch

Dec 09, 2020 - 12 min read
Jerry Ejonavi

A front-end framework helps developers create modern web applications called single-page apps (SPA). An SPA typically downloads the initial application code (HTML, CSS and JavaScript) from the server-side, and the subsequent resources are dynamically loaded to the page, usually in response to user actions.

React, Angular.js, Ember.js and Vue.js are some of the most popular front-end web frameworks in use today. Each one offers specific advantages and limitations over the others, but Vue.js is popular for being an ideal middle ground.

This tutorial will help you learn Vue.js quickly. We’ll go over the key concepts of the framework as we build a new Vue app.

Knowledge of JavaScript is a prerequisite for using Vue.js.

Today, we will learn:

Develop intermediate-level Single Page Applications with Vue.js

This course is an introduction to Vue.js. You will cover the crucial concepts, like directives, renderers, APIs, and components - all with hands-on practice.

Hands-on Vue.js: Build a fully functional SPA

What is Vue.js?

Created by Evan You in 2013, Vue.js is a progressive, declarative JavaScript framework for building fast single-page applications. It is progressive because it can easily scale from a library to a full-featured framework.

Vue offers an adoptable ecosystem that can scale between a library and a full-featured framework. It has become increasingly popular over the years, with 176k GitHub stars

Based on the MVC architecture, Vue (pronounced “view”) is focused on the view layer only, and it provides a system that lets you declaratively make changes to the DOM. This means that you don’t have to worry about how your application’s UI is rendered or how changes are applied to the DOM.

Under the hood, Vue utilizes a Virtual DOM to make the required changes to your application UI and state.

There are a number of ways to add Vue to a project.

Import it as a CDN package on the page

On an existing HTML webpage, add the following line of code near the closing <body> tag.

<script src=""></script>

Using a package manager

You can install Vue on an existing project by running npm install vue@next.

Alternatively, run yarn add vue@next if you are using the Yarn package manager. The @next tag tells our package manager to install the latest stable version.

Using the official CLI tool

Vue provides a Command-Line Interface tool, which can scaffold a project with predefined build setups for a modern frontend workflow.

Towards the end of this article, we’ll explore the benefits using the CLI provides and learn how to set up a production-ready project using a starter template.

Note that using the CLI requires familiarity with front-end build tools.


Vue.js compared to other frameworks

There are three popular JavaScript front-end frameworks:

  • Vue.js
  • Angular
  • React

All these frameworks share a similar philosophy and purpose. One of the main differences is that Angular was developed by Google, and React is developed by Facebook. Vue.js does not have a large tech company behind its development.

Vue.js is often considered a middle ground. It offers more tools than React but fewer than Angular. On top of that, the syntax of Vue.js is simpler. Vue.js also offers built-in state management and vue-router, the offical Vue.js router.

However, it does not feature HTTP client functionality or form validation. Vue focuses on building user interfaces and creating reusable components.

Vue.js also differs from other, smaller libraries.

  • jQuery is a small JavaScript library that makes vanilla JS easier to write. jQuery does have an additional build-step that Vue does not, which makes Vue more flexible.
  • Node.js is a cross-platform, back-end framework that executes JavaScript code on the server-side. Unlike Vue.js, no DOM is used.
  • Nuxt.js is a frontend framework based on Vue.js. Nuxt.js and Vue.js handle logic differently, since Vue always runs on the client side and nuxt does not.

Concepts and features of Vue.js

Vue’s design allows you to adopt as little of the framework as you want, making it easy to integrate into an existing project. Below, we’ll build a simple To Do application to demonstrate Vue’s ease-of-adoption while learning about the framework’s core concepts.

Vue.js File Structure

Like many other frontend frameworks, Vue.js allows users to split a web page into reusable components, each with its own HTML, CSS, and JavaScript to render it.


HTML Template and Vue CDN

Let’s start by creating an index.html file in a folder named vue-todo. Open a terminal and run the following commands:

mkdir vue-todo
cd vue-todo
touch index.html

We will start off with a blank HTML template and add Vue from a CDN. To do this, open the index.html file you just created with a text editor and add the following code:

<!DOCTYPE html>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<div id="app"></div>
<script src=""></script>

Including the Vue package via the CDN as we’ve done above makes the Vue object available globally. This object contains methods for creating application instances and registering components.

Creating an App Instance

Vue applications are typically organized into a tree of nested, reusable components. The component used as a starting point for the application, referred to as the root component, is rendered when we mount it to the DOM.

Vue provides a method called createApp() which accepts options to configure the root component and returns an application instance. We can then mount the application using the mount() method.

Continuing with our example, add the following code to set up your Vue application:

<script src=""></script>
<script type="text/javascript">
  const TodoApp = {};
  const app = Vue.createApp(TodoApp);

We’re using the <div> in our document as the target DOM node for our app. Note that we can pass options to the createApp() method.

Let’s initialize our to-do list as an empty array for now. Modify the TodoApp object to look like this:

const TodoApp = {
  data() {
    return {
      todos: [],

When a Vue instance is created, it looks for an element in the webpage to control. It can be defined by assigning that element an id (usually a div). This id is then mentioned in the Vue instance as the value of the el key.

<!-- This is the div that is assigned the id= 'app' -->
<div id='app'></div>
new Vue({
// This `id` is used as a value of `el` so that it knows
// which element `Vue` should be mounted on.
el: '#app'
Mounting the Vue instance

Template Syntax

If you have some experience with HTML and JavaScript, what we have done so far should feel familiar. This is one of the advantages of Vue.js over front-end frameworks like React and Angular.

Going back to our application, we will need a way to render items in our To Do list and add/remove items. For rendering data, Vue provides a straightforward way to do this.

First, add an example To Do list item to your array:

todos: [
    title: "Shop for Christmas",

Next, update your HTML to look like the following:

  <li v-for="todo in todos">
    {{ todo.title }}

The v-for attribute here allows us to link and render a list to the DOM. It is called a directive, and as you can already guess, it behaves like a JavaScript for-in loop.

Directives are prefixed with v- to indicate that they are special attributes provided by Vue. They apply special reactive behavior to the rendered DOM.

The use of double curly braces interprets data from a component instance as plain text. This is known as text interpolation.

JavaScript expressions are supported and will be evaluated as JavaScript in the data scope of the current active instance.

Components and Props

Components are reusable Vue instances that can be attached to an application or root component instance. They accept the same options as a root instance, such as:

  • data
  • computed
  • watch
  • methods
  • lifecycle hooks

A component has to be registered to an application instance before it can be rendered. We can do this with the component() method. You’ll find components very useful for keeping your codebases neat and organized when you start building larger applications.

Let’s make a few changes to our Todo application to see components in action. First, we’ll replace the start and end <li> tags with the following:

  v-for="todo of todos"

Next, add the following just before app.mount():

app.component("todo-item", {
  props: {
    title: String,
  template: `
      {{ title }}

You can see that we’ve created and registered a new component named todo-item to our app instance. The props property specifies data that can be passed to the component from its parent application or component instance.

The value provided to the template property should be a string containing HTML to be rendered.

Components are rendered in HTML by passing the component name to a custom tag. In our example app, this looks like <todo-item></todo-item>. The v-bind directive is used to bind an attribute or a component prop to an expression.

Here, we use it to dynamically pass data from our loop to the <todo-item> component.

Keep the learning going.

Learn how to build with Vue.js without scrubbing through videos or documentation. Educative’s text-based courses are easy to skim and feature live coding environments, making learning quick and efficient.

Hands-on Vue.js: Build a fully functional SPA


Component methods are accessible from within the component’s template. We can add methods to a component instance by passing an object with the desired methods to the component’s methods option.

Vue automatically binds the this value for methods so that it always refers to the component instance.

Note: You should avoid using arrow methods when defining methods, as that prevents Vue from binding the appropriate this value.

Take a look at an example of using methods in a component instance below.

const TodoApp = {
data() {
return {
todos: [
title: "Shop for Christmas",
todo: "",
methods: {
addTodo() {
if (this.$data.todo.length > 0) {
this.$data.todos.push({ title: this.$data.todo });
this.$data.todo = "";
<input v-model="todo" />
<button v-on:click="addTodo">Add todo</button>

Our component has been modified to have an extra data property, todo, the value of which we will bind to an <input /> tag in HTML. We also added a addTodo() method to create a new todo item with the value of the input.

v-model is a directive used to create two-way data bindings on form input, textarea, and select elements. It automatically picks the correct way to update the element based on the input type. The v-on directive listens for DOM events.

In our example, it’s used to invoke the addTodo() method when the button is clicked.

Code examples of Vue.js

Now that we understand the basics of how to create a Vue.js app, let’s dive more into the different functionalities with some code examples. These are common tasks that you’ll likely implement in your own apps.

Listen for when an element is clicked

Binding classes

Update an element’s content

Build a select input from an array

Advanced uses of Vue.js

Our setup so far (including a packaged build from a CDN) looks fine and works very well for small to medium-sized projects, where JavaScript is only used to enhance certain views. In more complex projects however, or when your frontend is entirely driven by JavaScript, these disadvantages become apparent:

  • Global definitions force unique names for every component
  • String templates lack syntax highlighting and require ugly slashes for multiline HTML
  • No CSS support means that while HTML and JavaScript are modularized into components, CSS is conspicuously left out
  • No build step restricts us to HTML and ES5 JavaScript, rather than preprocessors like Pug (formerly Jade) and Babel

All of these are solved by single-file components with a .vue extension. There are also many components, libraries, and open-source tools available that can enhance your app’s functionality and development experience.

You can make use of Vue’s CLI to quickly bootstrap a project with the most common tooling configurations setup for you. To get started, run the following command.

It will install vue-cli globally and make the vue binary available from anywhere on your command line.

// using npm
npm install -g @vue/cli

// using yarn
yarn global add @vue/cli

Once it’s installed, you can create a project by using the vue create app-name command. You will be provided with prompts about your project’s configuration. You can choose to go with a default or set up your own configuration.

Running this command with version 4.5 of the CLI gives the following output:


If you choose to use the Vue v3 preset, the command will create a project directory that looks like the following:


What to learn next

That’s all you need to get started using Vue with modern JavaScript tools and features to develop feature-rich applications!

While we’ve learned a lot building this really simple to-do application, we have barely scratched the surface of what Vue is capable of. There are also many more concepts still to learn, including the following:

  • Conditional rendering
  • Class and style bindings
  • Event and input modifiers
  • Vue.js plugins
  • Vuex: state management pattern

Educative’s course Hands-on Vue.js: Build a fully functional SPA will get you started on these concepts and more. You will also practically incorporate the concepts you learn by developing a fully working Vue.js Single Page Application that interacts with a backend server, APIs, and a database.

Throughout the course you will find quizzes and coding challenges to help strengthen your grasp of all the concepts.

Happy learning!

Continue reading about Vue.js

WRITTEN BYJerry Ejonavi

Join a community of more than 1.6 million readers. A free, bi-monthly email with a roundup of Educative's top articles and coding tips.