Getting Started with VueJS

11/09/2020

VueJS is a modern Javascript framework that makes it easy to handle data flow, simply by including attributes in your HTML tags.

In this guide, we'll be building a simple todo list app to get up and running with VueJS.

Setup and Installation

There are two ways to setup Vue: through a NodeJS project, or by including a script inside of your HTML file. Since we're just starting out, we'll use a script inside of our index.html file.

We can set up our index.html file like this.

<!DOCTYPE  html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Todooey - A Simple Todo List App</title>
    <link rel="stylesheet" href="style.css">
    <script src="https://unpkg.com/vue"></script>
  </head>
  <body>
    <div id="app">
    </div>
  </body>
</html>

In order to use Vue in our app, we need to create a new instance of Vue. We can do this using anotherscripttag before the closingbodytag.

<script>
  new Vue( {
    el: '#app',
  });
</script>

Now, we're able to use Vue in our app!

Creating Our App

Before we add the functionality to our app with Vue, we'll create the basic HTML/CSS structure with static content.

Inside of our HTML file, we'll create the Add Todo input, as well as the Todo list and each item

<div class="container">
  <h1 class="">My Todo List</h1>
  <div class="card">
    <div class="flex">
      <input placeholder="Add new todo" />
        <button>Add</button>
    </div>
  </div>
  <div class="card">
    <div class="card-inner">
      <h2>Todo</h2>
      <ul class="list">
        <li class="list-item">
          <div class="list-item-toggle"></div><span>Wash the car</span>
          <div class="list-item-delete">X</div>
        </li>
      </ul>
    </div>
  </div>
</div>

Then, we'll add some basic styling to our app inside ourstyle.cssfile.

html,
body {
  margin: 0;
  padding: 0;
  background: #faffff;
  font-size: 16px;
}

* {
  box-sizing: border-box;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
        Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  color: #3d4855;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  margin-top: 0;
}

.container {
  padding: 24px 0;
  max-width: 700px;
  width: 100%;
  margin: 0 auto;
}

.card {
  border-radius: 4px;
  box-shadow: 1px 1px 40px -10px #31505f30, 0px 1px 2px 0px #31505f30;
  background: white;
  margin-bottom: 24px;
}

.card-inner {
  padding: 16px 24px;
}

.flex {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

input {
  border-radius: 4px;
  background: transparent;
  border: none;
  width: 100%;
  padding: 14px;
  font-size: 16px;
  border: 1px solid transparent;
  height: 100%;
  display: block;
  outline: none;
}

button {
  background: #4fc08d;
  padding: 10px 22px;
  border: none;
  color: white;
  border-radius: 4px;
  margin: 8px;
  font-size: 16px;
  cursor: pointer;
  box-shadow: 1px 1px 15px -2px #212c4430;
  transition: 0.15s;
}

button:hover {
  background: #42aa7b;
}

button:disabled {
  background: #e8e8e8;
  color: #555;
  box-shadow: none;
}

.list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.list-item {
  padding: 12px 16px 12px 16px;
  border: 1px solid #e8e8e8;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  margin-bottom: 6px;
  border-radius: 4px;
}

.list-item:first-child {
  border-top: 1px solid #e8e8e8;
}

.list-item-toggle {
  border: 1px solid #e8e8e8;
  border-radius: 999px;
  height: 21px;
  width: 21px;
  margin-right: 16px;
}

.list-item-delete {
  margin-left: auto;
  color: tomato;
  margin-top: -2px;
  font-weight: bold;
  text-decoration: none !important;
}

.list-item.completed {
  border: 1px solid #4fc08d;
}

.list-item.completed span {
  text-decoration: line-through;
}

.list-item.completed .list-item-toggle {
  background: #4fc08d;
  border: #4fc08d;
}

Using Vue to Add Functionality

Great! Now that our app is styled, we can begin using Vue to create a dynamic todo list.

Displaying Our Todo List

To display our todo list, we'll take advantage of Vue's 2-way data flow. Inside of ourscripttag, we'll use Vue'sdataobject to create an array that will contain all our todo items.

<script>
  new Vue( {
    el: '#app',
    data: {
      items: [
		 {
		   id: 1,
		   name: 'Clean the fridge'
		 },
		 {
		   id: 2,
		   name: 'Walk the dogs'
		 },
      ]
    }
  });
</script>

Each todo item has a name and an ID, which will be used for removing items from the list later on.

Now that we have our data, we can display it in our list using thev-forattribute, which is basically aforEachloop that Vue uses.

<ul class="list">
  <li class="list-item" v-for="item in reversedItems">
    ...
    <span>{{ item.name }}</span>
    ...
  </li>
</ul>

Using thev-forattribute allows us to acces theitemproperty. We can display the name by using the double handlebars syntax:{{ item.name }}.

Adding Todo Items

Now that our items display properly, we can work on adding new items to the list. Using Vue'smethodsproperty, we can create a method that adds a new todo to the list.

First, let's create a new property inside ourdataobject, callednewItem.

<script>
  new Vue( {
    el: '#app',
    data: {
      newItem: '',
      items: [...]
    }
  });
</script>

This will be the value that we enter into the Add Todo input.

In order to make sure that what we type in our input updates thenewItemvalue, we can take advantage of Vue's 2-way data flow, using thev-modelattribute. This means that whatever value we enter into the input will be persisted to thedataobject.

<input v-model="newItem" placeholder="Add new todo"  />

Since we now have ournewItemvalue stored, we can create a method to add that item to the list.

Beneath thedataobject, we'll create a newmethodsobject with a function,addItem.

<script>
  new Vue( {
    el: '#app',
    data: {...},
    methods: {
      addItem: function() {
        this.items.push({
          id: this.items.length + 1,
          name: this.newItem,
          completed: false,
        });
        this.newItem = '';
      },
    },
  });
</script>

Basically, when this function is called, we're taking thenewItemvalue and pushing it to theitemsarray. The, we're clearing out thenewItemvalue, which clears our Add Todo input.

Now, all we need to do is call the function when we click the Add button. We can use thev-onattribute, or the@symbol for short.

<button @click="addItem">Add</button>

Now, Vue will know to call theaddItemfunction when this button is clicked.

As something a little extra, we can also disable the button is there is no value in the input, using the:disabledattribute. This tells Vue to apply the disabled attribute only if the expression inside the qoutes is true.

<button @click="addItem" :disabled="newItem.length === 0">Add</button>

Marking Items as Complete

The final thing that we need to do is add the ability to mark our items as complete.

To do this, we'll add a new property to each item in our array: thecompletedproperty.

<script>
new Vue({
  el: '#app',
  data: {
    items: [{
      id: 1,
      name: 'Clean the fridge',
      completed: true,
    },
    {
      id: 2,
      name: 'Walk the dogs',
      completed: false,
    }]
  }
});
</script>

Vue once again provides us with an attribute to dynamically change the class of an element, based on data in the Vue instance.

So, we can go to our list item and add the:classattribute.

<li class="list-item" :class="{completed: item.completed}" v-for="item in reversedItems">
  ...
</li>

This tells Vue that it should apply thecompletedclass to the<li>only if the item is completed (which we can tell by accessing theitem.completedproperty.

Now, our completed items should have a green outline. However, we still need to be able to mark them complete if they are not.

To do this, we'll create another method, calledtoggleComplete.

<script>
  new Vue( {
    el: '#app',
    data: {...},
    methods: {
      addItem: function() {...},
      toggleComplete: function (item) {
        item.completed = !item.completed;
      }
    },
  });
</script>

Once we have our method, we can call it using the@clickattribute that Vue provides.

<li class="list-item" :class="{completed: item.completed}" v-for="item in reversedItems">
  <div class="list-item-toggle" @click="toggleComplete(item)"></div>
  ...
</li>

Once again, we can pass in theitemobject as a prop to the function, because Vue allows us to access it via thev-forattribute.

Now, we can toggle each todo item between complete and uncomplete.

Deleting Todo Items

The final thing we need to do is allow ourselves to delete todo items. Once again, we'll use a method to accomplish this.

<script>
  new Vue( {
    el: '#app',
    data: {...},
    methods: {
      addItem: function() {...},
      toggleComplete: function (item) {...},
      removeItem: function (itemID) {
        this.items = this.items.filter((item) => newItem.id!== itemID);
      } 
    },
  });
</script>

In this function, we're accessing theitemIDprop (which is passed from the delete element) and setting theitemsproperty to a new array, without the item we just deleted.

Now, we can call the function from our delete element.

<li class="list-item" :class="{completed: item.completed}" v-for="item in reversedItems">
  ...
  <div class="list-item-delete" @click="removeItem(item.id)">X</div>
</li>

Tada! Now, we can succesfully delete our todo items!

Final Thoughts

So that's it! We've just build a functioning todo application using Vue. We learned how to call methods, access data and update data, all without any JS DOM manipulation.

You can find the full code for this app onGithub.

If you liked this tutorial, I'd appreciate it if you couldbuy me a coffee! Or, follow me onTwitter✌.