Vue.js for Beginners #2
- Vue.js for Beginners #1
- Vue.js for Beginners #2 ← You are here
Previously, we talked about some basic concepts in Vue, and in this article, we are going to dig deeper into this JavaScript framework, and event handling, data options, and components.
Event handling #
From our course on JavaScript basics, we learned that event handling is the most important concept in frontend development, and Vue.js, being a JavaScript frontend framework must have the same concept built in.
In this article, we are going to focus on two aspects, event handling with the directive v-on
, and form input handling with the directive v-model
. And before we could start talking about the script section of Vue.js, we are going to quickly go through style bindings, and class bindings.
An event is a user input, it could be a keyboard input or a mouse click, the user would usually expect some kind of response after the event takes place. The event handler listens to that event and it would perform some actions in the background and return something as the response. If you are not familiar with what an event is, there is a detailed explanation here: JavaScript Basics
The v-on
directive, which we can shorten to just the @
symbol, is used to listen to events in Vue.js. We can use it to specify what kind of event we are listening to, and what kind of action we are going to take after this event has been received.
|
|
That someAction
could be a simple JavaScript expression or a very complicated method, which allows us to build more complex logic.
|
|
Sometimes, the method requires up to pass some extra arguments.
|
|
It is also possible for one event to trigger multiple event handlers, and the handlers are separated using a comma. For example, this time, when a button is clicked, the browser will pop out an alert box as well as re-render the webpage:
|
|
Modifiers #
Modifiers are used to pass along extra details about the event. For example, we can use the .once
modifier to tell Vue that this event will only be triggered once:
|
|
This time, the “Add 1” button will only work once.
There are some other modifiers such as .prevent
, which stops the default action of an event. Or .stop
, which stops the event propagation. If you don’t know what they are, please read the article on Event Handling in the JavaScript course.
|
|
There is also a different type of modifier which makes the event handler listen to events from a specific key or a mouse button, or any of the combinations:
|
|
Form input binding #
The form is a very important component in web development, it provides a portal for the user to communicate with the backend. However, we know from our course on HTML Forms that forms could have a lot of different types of inputs, and each of them is associated with a different data type. It would be a pain in the neck if we try to process all those data types one by one.
Luckily, with Vue.js, we can use one single directive, v-model
, to bind all the input data, regardless of their data types. For instance, here we have a standard text input:
|
|
Here the user input has the type string
, and it will be bound to the variable massage
.
Multiline text input works exactly the same:
|
|
Checkbox #
|
|
As for the checkbox, the user input is a Boolean value, either true
or false
. In this example, the user input is bound to the variable checked
, and the directive v-if
will be used to check the truthiness of checked
.
However, sometimes in a form, there are multiple checkboxes, which means having only two values (true
or false
) would not be enough. In this case, we’ll need to add a value
attribute to each of the checkboxes:
|
|
Notice this time, the variable checkedBoxes
is bound to an array, and when a box is checked, its value (whatever you assigned to its value
attribute) will be appended to that array.
Radio #
Radio is kind of like a multi-checkboxes group, except, you can only pick one option. So in this case, the user input will always be a single string.
|
|
The variable picked
will be a string instead of an array.
Select #
For a single select, the variable is a string type.
|
|
For a muliselect, the variable will be bound to an array.
|
|
Style binding #
Class binding #
From our course on CSS Basics, we know that class is how we can assign the same CSS code to different HTML elements, and by changing the class name, we can easily change the CSS code associated with that element.
We can change the class name of an HTML element dynamically in Vue.js like this:
|
|
In this example, active
is a class name, and isActive
is a variable with a Boolean value. If isActive
is true
, then the class name active
will be rendered.
We can have multiple class names in here:
|
|
CSS binding #
We can also bind CSS codes directly like this:
|
|
Although it is usually better to put the object inside the data() method, so that our template section looks cleaner:
|
|
Now, it is finally time for us to dive into the most important part of this course, the script section of a Vue application. To master a web framework, the most important step is to understand how data could circulate inside your project, and how different types of data are treated differently. That would be the focus of this article.
In this article, we are going to talk about several different types of data options. Do not confuse data options with the data
method we talked about before. The data
method is a method where we declare a list of variables that we are going to use in the component instance, and data options is a collection of properties and methods that deals with data in Vue.js, which includes the data
method.
After that, we are going to discuss the lifecycle hooks, which are interfaces that allow us to inject codes at different stages of a component instance’s creation.
Data options #
data
#
First of all, the data
method. Like we’ve seen over and over again, it is a method that returns an object, and inside that object, we define all the variables we need for this component instance. Vue.js will automatically wrap these variables inside its reactivity system, meaning that when the value of the variable changes, the webpage automatically rerenders to reflect the changes.
The variables are only added as the instance was being created. You can, in fact, assign variables after the instance has already been created, but that variable will not be a part of the reactivity system. So, you should always create them inside the data
method, if there isn’t an initial value, you can use a placeholder value such as null
or undefined
.
|
|
methods
#
The methods
is another data option we are already familiar with. It is the place where we define all the logic for our application. When you create a method, Vue.js will automatically bind the this
keyword to that method. So, to access the value of a variable for the current instance, you need to use this.variableName
.
|
|
computed
#
The computed
property is very similar to the methods
property. It is also a place for us to store methods that deal with data. However, computed is usually for getters and setters. The getters are methods that return the value of a variable, and setters are methods that assign a new value for a variable.
|
|
It seems like we could have done this with methods
, so why does Vue have both methods
and computed
, and what exactly is their difference? The two approaches here indeed produce the same result, their difference, however, is that the computed
is cached while the methods
is not.
When a computed
method is invoked, the computations will perform once and the result will be stored in the cache. The method will not reevaluate as long as the variables that it depends on have not changed. While in the case of methods
, every time a re-render happens, it will perform the computation all over again.
Using computed can save you a lot of trouble if you are dealing with a large amount of data that would be very expensive to compute over and over again.
watch
#
The watch
property defines methods that will run whenever a variable changes its value. It essentially provides us with a way to customize our own reactivity system.
|
|
In this example, whenever the value of count
changes, the page will not only re-render, it will also output a message in the console, telling you the difference between the old value and the new value. Rember that the name of the method and the name of the variable must match.
That’s not all, in fact, there are three other data option, props
, emit
and expose
. However, to understand these data options, we need to first dig deeper into the component system of Vue.js. We’ll talk about them in the next article.
Lifecycle hooks #
Lifecycle Hooks | Details |
---|---|
beforeCreate | Called immediately after the component instance has been initialized. This is before the data and the event listener has been setup. You cannot access them at this stage. |
created | This is after the component has been created, and the data options has been processed. However, the mounting has not started, which means the component hasn’t yet appeared on the webpage. |
beforeMount | Right before the mounting starts. |
mounted | Called after the mounting has finished. This does not guarantee that all child components has been rendered. |
beforeUpdate | After the data has changed but before the DOM structure change. This would be a good place to access the existing DOM before any changes happen. |
updated | Called after the DOM has been re-rendered. It is usually better to use watchers to react to data change instead. |
In the final part of the course, we are going to investigate the component system of Vue.js. Here is an example of a component.
components/ComponentOne.vue
|
|
We can use this component inside our App.vue
file:
|
|
Components are reusable, we can create multiple instances of the same component on one page. And they are all independent of each other, if the state of one instance changes, it will not affect the others.
components/ComponentOne.vue
|
|
App.vue
|
|
We can also import a component inside another component, forming a nested structure.
components/ComponentOne.vue
|
|
components/ComponentTwo.vue
|
|
Organizing components #
In fact, it is very common for a real-life application to have a nested structure like this:
For example, here we are trying to build a frontend for a blog, and we need a list of recent articles. In real-life applications, the data is usually stored inside a database, and we have a backend that will retrieve the correct information and send it to the frontend. For now, we’ll just assume we have a fully functional backend, and the data has already been sent to us.
App.vue
|
|
components/PostListComponent.vue
|
|
components/PostComponent.vue
|
|
As you can see, we only have one PostComponent.vue
, and it is reused multiple times using a v-for
loop. This will save us a lot of trouble since we don’t have to rewrite the same code over and over again.
Passing data to child #
Now we face a new problem, we know that by default, component instances are isolated from each other, the data change in one instance does not affect others since we cannot access the data in another instance. However, what if we need that to happen?
For instance, in our previous example, in the place where it should be the title of the article, we had to use a placeholder text instead, because the data about the post are in the parent component (PostListComponent.vue
), and we cannot access them in the child component (PostComponent.vue
). We need to somehow pass the data from the parent to the child.
That can be achieved using the props
option.
components/PostListComponent.vue
|
|
components/PostComponent.vue
|
|
Let’s take a closer look at how data flows in this example. First, we bind the title of the post to the variable title
, and pass that variable to the PostComponent
. The PostComponent
receives the variable title
with props
property, and then uses it in the template.
It is also possible for us to validate the transferred data in the child component using the object syntax instead of an array.
components/PostComponent.vue
|
|
However, it doesn’t matter which syntax you are using, this data flow is one way only. It is always from the parent to the child, if the parent changes, the child changes, but not the other way around. You should not try to update a props
in a child component. Instead, the best practice is to declare a new variable in the child and use the transferred props
as its initial value.
components/PostComponent.vue
|
|
Passing event to parent #
When we are building a web application, sometimes it is necessary to communicate from the child component to the parent component. For example, let’s go back to our post list example, this time we add a button in the PostComponent
, and every time the user clicks on the button, it enlarges the font for the entire page.
To do this, it would require us to transfer the click event which happens in the child component to the parent component, and when the parent component catches that event, it would change the value of the corresponding variable (the variable that stores the size of the font). This can be done using the emits
property.
components/PostComponent.vue
|
|
components/PostListComponent.vue
|
|
The event starts from the child component, when the button is clicked, it emits an event called enlargeText
using a built-in function $emit
, and that event is declared in the script section using the emits
property. And when the event gets caught by the parent component, the parent changes the value of the variable titleFontSize
.
Now, what if we want to try something more complex? What if we want to specify font size using a text box instead of just a button? This would require us to transfer some data to the parent along with the event.
components/PostComponent.vue
|
|
components/PostListComponent.vue
|
|
If you think my articles are helpful, please consider making a donation to me. Your support is greatly appreciated.