Vue.js for Beginners #1
Tags: vue, javascript, programming
Published: 2023-04-11 20:06:30

Vue is a frontend JavaScript framework that helps us quickly create user interfaces. It is more lightweight and beginner-friendly compared to other frameworks such as React or Angular. The core library of Vue focuses on the view layer only, which is the part that the users can see. That is also why the author named the framework Vue (pronounced as view).

## Installation

To create a new Vue application, go to the terminal and run the following command:

```cmd
npm init vue@latest
```

This command will prompt you with multiple options such as TypeScript, Vue Router, and Pinia. For this tutorial, we don't need any of these features, but you can play around with them if you want.

```text
✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ./<your-project-name>...
Done.
```

Next, go to the project folder, install the necessary packages, and run the development server.

```cmd
cd <your-project-name>
npm install
npm run dev
```

Open your browser and go to http://localhost:3000/, you should see Vue's welcome page.

![Vue welcome](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u9gryuef6172hihzrtcr.png)

## Introduction

Before we start, let's take a look at what has been installed into our project folder.

![Vue directory structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uckk72rm0ahuyybyliuk.png)

There are a few things we are already familiar with. The `node_modules` contains the packages we installed. The `public` folder contains the files and resources that we wish to make public. The `package-lock.json` and `package.json` files are both for managing packages, which we talked about before in the [JavaScript Basics](/posts/javascript-basics-5/) tutorial, and the `index.html` file is the start point of our project.

For this tutorial, we'll only focus on the files inside the `src` directory. The `assets` folder stores the images, CSS files and other resources. The `main.js` file mounts and configures all the Vue apps in our project, and it is also the script that we import into the `index.html` file.

The `App.vue` is the actual Vue app, this is where we do most of the coding. However, sometimes the app gets too big, it makes more sense if we divide the app into multiple components, we'll store these components inside the `components` folder.

We'll take a closer look at what happens when you go to [ http://localhost:3000/](http://localhost:3000/). Let's start from `index.html`, and notice what we have inside the `<body>` tag.

```html
<body>
  <div id="app"></div>
</body>
```

The only line of the code that matters is `<div id="app"></div>`. Why? Let's go to `main.js`.

```javascript
import { createApp } from "vue";
import App from "./App.vue";

createApp(App).mount("#app");
```

This file imports the Vue app, and mounts that app to the HTML element with `id="app"`. Recall that `#` represents id and `.` represents class. This is why that `<div>` element is so important, even though it is empty.

Next, go to the `App.vue` file:

```vue
<script setup>
import HelloWorld from "./components/HelloWorld.vue";
</script>

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Hello Vue 3 + Vite" />
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  ...;
}
</style>
```

We immediately see that the file is divided into three sections. The `<script>` section contains the JavaScript code, the `<template>` contains HTML elements, and `<style>` contains CSS codes.

Notice in the `<script>` section, we imported a component from the `components` folder and used it in the `<template>` section.

And finally, go to the `HelloWorld` component. You can see that it has the exact same structure. You can also try to edit something inside this file and see if the webpage changes.

## Basics

Now, let's go back to the `App.vue` file, and delete everything unnecessary so we'll have a clean and empty vue document.

```vue
<script></script>

<template></template>

<style></style>
```

### Methods and properties

As you know, the `<script>` section is where we write JavaScript code, but since Vue is a framework, there are a few restrictions and requirements. This section usually has the following structure:

`App.vue`

```vue
<script>
export default {
  data() {
    return {
      name: "value"
    }
  },

  methods: {
    xxx() {...}
  },
  ...
}
</script>
```

This means when you are importing this Vue app into `main.js`, you are actually importing a bunch of methods and properties. Each property/method serves a different purpose.

For example, the `data()` method returns an object containing all the variables that are used in the app. Be careful that `data` must be a method and not just a property, this is what makes Vue reactive, meaning if the value of the variable changes, the web pages changes without having to reload. The `methods` property contains all the methods that are created by you, the coder. Of course, there are other properties allowed such as `props`, `computed`, `inject` and `setup`. We'll discuss them in detail in the future.

### A simple counter app

Knowing just these two simple concepts, the `data` method and the `methods` property, is enough for us to start creating apps. For example, we'll create an app that counts how many times a button has been clicked.

`App.vue`

```vue
<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
};
</script>

<template>
  <button v-on:click="count++">click me</button>
  <p>count = {{ count }}</p>
</template>
```

First, we declare a variable `count`, whose initial value is 0, and in the `<template>` section, we set up an event listener (`v-on:click`), each time the button is clicked, `count` increments by 1. The variable will then be rendered using double curly braces (`{{ }}`). We'll talk about these syntaxes later.

What if we want another button that resets the value of `count`? This is what we can do:

`App.vue`

```vue
<script>
export default {
  data() {
    return {
      count: 0,
    };
  },

  methods: {
    clear() {
      this.count = 0;
    },
  },
};
</script>

<template>
  <button v-on:click="count++">click me</button>
  <button v-on:click="clear()">clear</button>
  <p>count = {{ count }}</p>
</template>
```

Remember to use the keyword `this` when referring to variables that belong to **this** application instance. The variable that we defined in the data method is unique to this instance, meaning it cannot be accessed by other instances or components. For example, we can create another counter, and import it into `App.vue` as a component.

`components/Counter.vue`

```vue
<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    clear() {
      this.count = 0;
    },
  },
  components: { Counter },
};
</script>

<template>
  <button v-on:click="count++">click me</button>
  <button v-on:click="clear()">clear</button>
  <p>count = {{ count }}</p>
</template>

<style></style>
```

`App.vue`

```vue
<script>
import Counter from "./components/Counter.vue";
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    clear() {
      this.count = 0;
    },
  },
  components: { Counter },
};
</script>

<template>
  <button v-on:click="count++">click me</button>
  <button v-on:click="clear()">clear</button>
  <p>count = {{ count }}</p>

  <Counter />
</template>

<style></style>
```

![Counter](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vgmo5niswb7l5kjmws85.png)

Try this in your own browser, and you will find that even though the variable we defined for `Counter.vue` and `App.vue` are both `counter`, they do not seem to affect each other, and when you reset the variable's value, only the one in the same instance becomes 0.

### Lifecycles

Finally, I'd like to introduce another important concept in Vue, it's called lifecycles.

When an app instance is been created, it goes through a series of processes, such as initializing data, compiling the template, mounting the template onto the DOM, and updating the template as the data changes. This allows us to divide the life of an application instance into several stages, and Vue provides us with several lifecycle hooks that allow us to add our own code at different stages.

For example, the function `created()` allows us to add code that is supposed to run right after the instance has been created.

```vue
<script>
export default {
  data() {
    return { count: 1 };
  },
  created() {
    console.log("initial count is: " + this.count);
  },
};
</script>
```

There are other lifecycle hooks that we could use. Here is a diagram showing all of them and where they are in the lifecycle.

![Lifecycle](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rl5pgsqg5fhl10a9vwyy.png)

## Interpolations

In the first section of this article, we learned that a Vue file is divided into three sections, `<template>`, `<script>`, and `<style>`. However, we merely touched the surface of Vue.js last time, starting from now we are going to talk about the details of each of these sections, and we'll start with the easiest, the template section.

We know that the template section only contains HTML codes, it shows what the Vue file will eventually be rendered into. However, it can't be that simple, since we want the page to be reactive, we want it to change as the data changes. To do that, we need to inform Vue.js where to put the data.

### Text

Text interpolation is the most basic form of data binding, which uses double curly braces like this:

```vue
<script>
export default {
  data() {
    return { msg: "This is a message." };
  },
};
</script>

<template>
  <p>Message: {{ msg }}</p>
</template>
```

Try to change the value of `msg`, and you'll see that the page changes without having to be refreshed.

### Raw HTML

However, what if we want the data to be more complex? Say we want to bind a piece of HTML code to a variable, see what happens when you try to output HTML with double curly braces:

```vue
<script>
export default {
  data() {
    return { msg: '<span style="color: red">This is a message.</span>' };
  },
};
</script>

<template>
  <p>Message: {{ msg }}</p>
</template>
```

The data will be treated as plain text instead of HTML codes. To solve this problem, we need to tell Vue.js that the data we are trying to render is HTML, by using an HTML directive:

```vue
<p>Message: <span v-html="msg"></span></p>
```

This time, when the data is being rendered, the original `<span>` tag will be replaced.

### Attributes

Sometimes it might be useful if we bind an attribute to a variable. For instance, we want to enable a button when the user is verified, and disable it when the user is not verified. We can bind the `disabled` attribute to the `verified` variable by using the `v-bind` directive.

```vue
<script>
export default {
  data() {
    return { verified: false };
  },
};
</script>

<template>
  <button v-bind:disabled="!verified">Button</button>
</template>
```

Remember that the exclamation mark (`!`) inverts the value of `varified`.

### JavaScript expressions

It is also possible for us to use simple JavaScript expressions inside the template. In fact, the `!varified` we just saw is a very simple example. We can also do something more complicated like these:

```vue
{{ number + 1 }}

{{ ok ? "YES" : "NO" }}

{{ message.split("").reverse().join("") }}

<div v-bind:id="'list-' + id"></div>
```

However, there are some restrictions, for example, statements that declare new variables are not going to work. Loops and flow controls (`if` statements) are not going to work either.

## Directives

In Vue.js, directives are special attributes with the prefix `v-`. Their primary function is to bind a side effect to a DOM node.

For instance, the following example binds a variable to the `<p>` element using the `v-if` directive. It works just like a regular `if` statement. When `verified` is `true`, the first `<p>` element will be rendered, and when `verified` is `false`, the second `<p>` element will be rendered.

```vue
<p v-if="verified">You are verified.</p>
<p v-if="!verified">You are NOT verified.</p>
```

### Arguments

Some directives can take extra arguments. For example, the `v-bind` directive, which we've already seen, is used to bind an HTML attribute to a variable and it takes the name of that attribute as an argument.

```vue
<p v-bind:color="colorName">...</p>
<button v-bind:class="className">click me</button>
```

Another example is the `v-on` directive. It is the event listener in Vue.js.

```vue
<a v-on:click="action">...</a>
```

When this link is clicked, the function that is bonded to the variable `action` will be executed.

It is also possible to bind the argument itself to a variable. For example:

```vue
<a v-on:[event]="action">...</a>
```

In this case, if `var event = "click"`, this example will be equivalent to `v-on:click="action"`.

In fact, `v-bind` and `v-on` are the two most commonly used directives, that is why Vue.js has created special shortcuts for them. The `v-bind` can be shortened to just a colon (`:`), and `v-on` can be represented using just `@`.

The following codes are equivalent:

```vue
<a v-bind:href="url">...</a>
<a :href="url">...</a>
```

```vue
<a v-on:click="action">...</a>
<a @click="action">...</a>
```

### Flow Control

Next, let's talk about the `if` statements in Vue. Like we've seen before, the `v-if` directive binds the element with a boolean value. If the boolean value is `true`, the element will be rendered, and if it is `false`, the element will simply be ignored by Vue.

Other than `v-if`, there is also a `v-else` directive, which works with the `v-if` directive:

```vue
<p v-if="verified">You are verified.</p>
<p v-else>You are NOT verified.</p>
```

What if you need more than just two conditions? The `v-else-if` directive, as the name suggests, creates an `else if` block. It can be chained multiple times, hence creating multiple conditions.

```vue
<p v-if="num === 1">The number is 1.</p>
<p v-else-if="num === 2">The number is 2.</p>
<p v-else-if="num === 3">The number is 3.</p>
<p v-else-if="num === 4">The number is 4.</p>
<p v-else>The number is 5.</p>
```

### Loops

Finally, other than `if` statements, Vue also allows us to create simple `for` loops inside the template. Its syntax actually resembles the `for` loops in Python, if you are familiar with the language.

We can render a list of items in an array like this:

```vue
<script>
export default {
  data() {
    return {
      items: [{ num: 1 }, { num: 2 }, { num: 3 }, { num: 4 }, { num: 5 }],
    };
  },
};
</script>

<template>
  <ul>
    <li v-for="item in items">The number is {{ item.num }}.</li>
  </ul>
</template>
```

Vue also supports an optional second argument for index number:

```vue
<template>
  <ul>
    <li v-for="(item, index) in items">
      #{{ index }} - The number is {{ item.num }}.
    </li>
  </ul>
</template>
```

> If you liked this article, please also check out my other tutorials:
> - [Django for Beginners](https://www.ericsdevblog.com/posts/django-for-beginners-1/)
> - [Laravel for Beginners](https://www.ericsdevblog.com/posts/laravel-for-beginners-1/)
> - [Create a Modern Application with Django and Vue](https://www.ericsdevblog.com/posts/create-a-modern-application-with-django-and-vue-1/)
> - [Beginner’s Roadmap to Web Development](https://www.ericsdevblog.com/series/beginners-roadmap-to-web-development/)