Vue.js for beginners
Tags: vue, beginners, javascript, tutorial
Published: 2023-04-04 10:00:39

# Introduction
This tutorial is a starting point for anyone getting started with Vuejs.

### Prerequisites
You will need a nodding acquaintance with the basics of Vue such as *v-on*, *v-bind*, *refs* etc. Please refer to the [official documentation](https://vuejs.org/guide/introduction.html) for Vue.js if you feel unfimiliar with a terminology at any point.

### Topics
Following are the topics we will be taking a look at:
 - Single File Components
 - Props and  Events
 - Routing
 - Composables

### Source Code
To follow along with the tutorial, you can find the source code [here]().

---

# Setup
For a better developer experience, we will be using **vite** along with **tailwindcss**.

### How to install?
To get started with vite and tailwind, simply follow the [official guide](https://tailwindcss.com/docs/guides/vite#vue).

### Cleanup
 1. Navigate to `my-project/src` and remove the everything except for `main.js`, `style.css` and `App.vue` files. 
 2. Remove everything in `App.vue`, we will come back to it in a minute.

---

# Single File Components
A [single file component](https://vuejs.org/guide/scaling-up/sfc.html) (SFC) is a special file format that allows us to encapsulate the template, logic and styling of a Vue component in a single file. These files are named as `*.vue`, where `*` is the name of component in *UpperCamelCase*.

### Constraints
A Vue SFC must have atleast one `<sricpt>` or `<template>` tag. However, Vue will give a **warning** if no `<template>` tag is provided to an SFC.

### Example
Create a new folder in the `src` directory and name it `components`. Create a new file in `src/components` with the name `Oven.vue`.

![oven component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a22zeg7gcgk6pngqygmk.png)

##### What is happening?
 1. We bind the `disabled` property of `<button>` to the `isBusy` ref. Any time the value of `isBusy` changes, our button will listen to the change and re-render (if needed).
 2. We also provide a listener `v-on:click` or `@click` to the `<button>` component and assign it a *handler* function. This *handler* is executed every time the button is pressed.

Add the oven to App.vue and test it.

![App component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h1r64950vxsl24fokfbu.png)



![Program Run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/47q1ebvqpz0f1d42hwna.png)

### Views
Views in Vue are exactly the same as Vue components. The components that act as *views* or *pages* for routing are referred to as views.

##### Example
 1. Create a new folder in the `src` directory and name it `views`.
 2. Add a new file in `src/views` with the name `Kitchen1.vue`.


![Kitchen1 view component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kydtuy2a3ksyyu73nehi.png)



Our kitchen only contains a single oven for now.

Let's also update the `App.vue` file:

![Add Kitchen1 to App](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ye2hshoe155iq7wrgr5l.png)



![Program Run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/370rtaotjl6v78uu7unp.png)

---

# Props
Props are attributes that are passed to a Vue SFC via the parent component. They can be declared using the `defineProps` macro when using `<script setup>`. This function returns an object containing all the passed props.

### Receiving props
Let's change the oven component to bake whatever we want instead of just a cake.

![Add props to Oven component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1rnnh1vcr0q2yxyoe96v.png)



We will also need to change the `bakeACake` function and `prompt` logic.

![Add logic to Oven component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9lkpu8axwdpybomnh85l.png)



### Passing props
I say we bake a banana bread this time.

Go to `views/Kitchen1.vue` and pass `food` and `duration` props to the oven.

![Passing props to component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ailzaphos70nft2uclxk.png)


Notice that we pass `banana bread` as a static string but *bind* the `duration` property to `3000` even though it is static. This is because we need to tell Vue that this a Javascript expression (a number in our case) instead of a string.

Let's see how it works:

![Program Run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7dgs4f8drugefr7muqj.png)

---

# Events
What if our kitchen had multiple ovens to bake different food items and we wanted to keep track of all the items currently being baked?

##### Solution  
 1. Create multiple ovens.
 2. Add to 'currentlyBaking' when an oven is started.
 3. Listen to the event when a food item is baked and remove it from the `currentlyBaking` list.

##### Create multiple ovens
Navigate to `views/Kitchen1.vue` and initialize a constant list `ovens`

![Create ovens list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/na5o061ps1blga4lwg10.png)


Now replace the `<Oven />` tag with a `v-for` directive that will render the `ovens` list.

![Using v-for to render ovens](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/55s40tz08kjxdzttsfid.png)


![Program Run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23y79hhkk6zcahumr4ab.png)

##### Emitting events
We need our oven to tell the kitchen when it starts baking an item as well as when it finishes. To accomplish this task, we will simply emit events from the oven component.
Navigate to `components/Oven.vue` and define *start* and *baked* events using the `defineEmits` macro.

![defining emits for oven](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3n51y5yf024vi05tbynv.png)



Let's also emit these events using the `emit` function.

![emitting events for oven](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txakwf4x2i6v3m6o1sjh.png)



##### Listening to events
Now that our ovens are able to communicate their status with the parent component, the only thing that is left to do is to listen to their events.

Navigate to `views/Kitchen1.vue` and add the following logic:

![logic for Kitchen1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dsz7b4l656jh3vvi6h6h.png)


The `currentItems` list is what we want to render to the screen. This can be easily achieved using the `v-for` directive, just like we did for the `ovens` list.

![Rendering current items](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92abc4hwyh3i7l39h6z9.png)


We assign `addToCurrentItems` and `removeFromCrrenltItems` handler to the `start` and `baked` events respectively.

Now if we run the app, our kitchen will have all the info it needs.

![Program Run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4jymop8sdqf2vhgm9erw.png)

---

# Routing

A single kitchen won't be able to cope with a high number of orders. So let's add two more.  
Navigate to `src/views` and two files `Kitchen2.vue` and `Kitchen3.vue`. `Kitchen2` is just like `Kicthen1` while `Kitchen3` is under maintenance and is inaccessible.

But how do we navigate between all these rooms? I hear you ask. Well, the answer is simple:
 1. Define all routes
 2. Create a router
 3. Add a navbar
 4. Assign it to the `app` component

### Define route options
Create a new folder `router` inside `src` and create an `index.js` in `src/router`.  
Here, we define an array `routes` containing the navigation options for each route (or kitchen).

![Define navigation routes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bdp4a2zm9z7vj0pot96f.png)



### Creating a router instance
Creating a router instance is simple:

![Create a router](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d63620ngbei98ernzet2.png)


##### What is happening?
We define a vue router instance using the `createRouter` macro which takes in a history mode as well as an array of route options. A route option simply needs a `path`, an optional `name` (this is useful for named routes. See [named routes](https://router.vuejs.org/guide/essentials/named-routes.html) for more detail), and a `component` to render, where the `component` is a *view*.

### Adding a Navbar
We also need a `NavBar` to easily navigate between the kitchens.<br>Create a new file `NavBar.vue` in the `components` directory and use the `<router-link>` tag to create navigation links.

![Create a navbar using router-link](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fzyu11b1sxkjgc39d3v2.png)



`<router-link>` acts like a `<a>` tag however, it has several benefits.
> *This allows Vue Router to change the URL without reloading the page, handle URL generation as well as its encoding.*

### Using the router
Navigate to `src/main.js` and alter your code to match the following:

![Assign router to app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qn1xzhyqt49efi1clx1t.png)



But how does the 'App' component know where to render these components (views)? Well, we tell it of course.<br>Head over to `src/App.vue` and add a `<router-view>` tag inside the template.

![User router-view in App component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56itfm0am4b5xusqirfb.png)



Our restaurant is looking clean and we can easily navigate between the kitchens.

![Program Run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6dqlpud3s2lypb12vgkq.png)

##### What about kitchen3?
You forgot didn't you? Kitchen3 is barred! and you can not enter it.<br>In order to block all entrances, we need to intercept calls made to the `router`. This can be easily done by using a [navigation guards](https://router.vuejs.org/guide/advanced/navigation-guards.html) known as `router.beforeEach`.  
Head over to `router/index.js`, and add the following code:

![Block entrance for Kitchen3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4fgj9eieauyabtmrqjyz.png)


##### What is happening?
The `router.beforeEach` is called every time we make a navigation call to the `router`. Here, we have access to `to` and `from` routes and we may explicitly `return false` to cancel the navigation.

![Program Run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xt8ft0wqufsfg2nlksiy.png)

---

# Composables
You may have noticed that we duplicated all our code logic from `Kitchen1.vue` to `Kitchen2.vue`, which of course, is not ideal. And that is where we use **[composables](https://vuejs.org/guide/reusability/composables.html)**.  
> *a "composable" is a function that leverages Vue's Composition API to encapsulate and reuse stateful logic.*

##### Key points
 - They become more and more vital as the code base scales.
 - In addition to **reusability**, composables also provide **readablity**.
 - I usually give each composable file the same name, in **lowerCamelCase**, as the function it exports.

### Extracting reusable code
Create a new folder in the `src` directory with the name of `composables` and add new file `getCurrentKitchenItems`. Define a function with the same name that encapsulates the logic for items that are currently being baked.

![Extract reusable stateful logic to composable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujbv0609ed3qxtbm38gr.png)

Now in both of our functioning kitchens, we can do:

![Using the composable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0entz170qznmkpfnkl6.png)

**Much cleaner!** And our kitchens work smoothly as well.<br>
Behind the scenes, I also added a `CoffeeMaker` component (which works just like an `Oven`).<br>You can imagine how our code would bloom up, had we not used composables.

![Program Run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kroad5mwyyv6irqcifry.png)


# Wrap up
And with this, our little session comes to an end. You can keep adding more and components and custom logic to this project. The benefit of following **Vue**'s conventions is that your code base is highly scalable.  
Just remember to take it one step at a time, and keep finding motivation.  
HAPPY LEARNING!!!