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 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.
Cleanup
- Navigate to
my-project/src
and remove the everything except formain.js
,style.css
andApp.vue
files. - Remove everything in
App.vue
, we will come back to it in a minute.
Single File Components
A single file component (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
.
What is happening?
- We bind the
disabled
property of<button>
to theisBusy
ref. Any time the value ofisBusy
changes, our button will listen to the change and re-render (if needed). - 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.
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
- Create a new folder in the
src
directory and name itviews
. - Add a new file in
src/views
with the nameKitchen1.vue
.
Our kitchen only contains a single oven for now.
Let's also update the App.vue
file:
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.
We will also need to change the bakeACake
function and prompt
logic.
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.
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:
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
- Create multiple ovens.
- Add to 'currentlyBaking' when an oven is started.
- 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
Now replace the <Oven />
tag with a v-for
directive that will render the ovens
list.
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.
Let's also emit these events using the emit
function.
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:
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.
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.
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:
- Define all routes
- Create a router
- Add a navbar
- 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).
Creating a router instance
Creating a router instance is simple:
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 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.
Create a new file NavBar.vue
in the components
directory and use the <router-link>
tag to create navigation links.
<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:
But how does the 'App' component know where to render these components (views)? Well, we tell it of course.
Head over to src/App.vue
and add a <router-view>
tag inside the template.
Our restaurant is looking clean and we can easily navigate between the kitchens.
What about kitchen3?
You forgot didn't you? Kitchen3 is barred! and you can not enter it.
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 known as router.beforeEach
.
Head over to router/index.js
, and add the following code:
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.
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.
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.
Now in both of our functioning kitchens, we can do:
Much cleaner! And our kitchens work smoothly as well.
Behind the scenes, I also added a CoffeeMaker
component (which works just like an Oven
).
You can imagine how our code would bloom up, had we not used composables.
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!!!
Top comments (0)