The Complete Vue.js Event System Guide That The Official Doc Didn’t Explain In Detail — Part 1
Vue.js is implemented with a powerful yet easy-to-use event system that covers most of our daily development needs when it comes to user interaction. In this series, we will go through all parts of the event system in Vue that you could possibly use in your projects.
Let’s start off with Event Handling.
Here’s a simple Vue component with a line of text and a button:
When the user clicks on the button, we want to show a dialog with a message. So we need to bind a click event onto the
<button> element. To bind an event onto an element in Vue's template, we can use Vue's
v-on directive, and the event is the built-in
Normally we will use
This means when the
<button> element is clicked, Vue will try to find a callback function (event handler) named
showDialog and execute it. We now need to define this function.
Will it work when clicking the button?
It won’t work, and we got the error in the console:
“Property or method “showDialog” is not defined on the instance…”
This indicates the callback function must be defined on the instance, in our case here, on a
VueComponent instance (because we are within a Vue component). The place to put a function on a
VueComponent instance is the
methods option, so let's move the callback into it:
The alert dialog is now shown.
@xxxx to bind (listen to) an event.
xxxx is the event name that can be a built-in event such as
click, or a custom event.
showDialog method get arguments? Yes, actually if we add a parameter in the function definition and print it out after clicking:
We can see it is the event object (of type
PointerEvent, which is the native DOM event). Because it is the native event, we can access its
By default, Vue will pass the native DOM object as the first argument into the event callback function (event handler).
Now if we want to pass an argument to
showDialog from the
template, we can put the argument in the parenthesis after the method name. For example:
It works as expected, but we might still want to access the event object, so can we do this?
No, the output is
undefined. To solve this issue, Vue implemented a keyword
$event, and if we add it as the second argument in the template:
The method receives the event object.
$event works like a placeholder in Vue's template. When Vue parses the template and scans the
$event, it will replace it with the DOM event object.
Can we switch the order of
$event, like this?
$event will be passed to the 1st parameter defined in the method, and
text to the 2nd parameter.
The order of arguments in the template is the order they are passed to the parameters of the event callback.
@click="showDialog()"works the same as
@click="showDialog($event)", the difference is the second form allows you to access the event object and pass arguments.
`this` inside event callbacks
Now let’s look at the
this inside our event callback method by printing it out:
It points to the current component, that is, a
VueComponent instance. On this instance, we can see the event callback
showDialog defined in the
methods option. The
ƒ showDialog(event, text), which means Vue will execute this
ƒ showDialog(event, text) function when the event is triggered. Also
[[BoundThis]] indicates the
this keyword in
showDialog is bound to the current
VueComponent instance (current component). This is automatically done by Vue, and we can verify it:
We created a
data property and save the value of
mounted, which points to the current component instance. Then in the
showDialog method body, we do a comparison, and both
this.instance point to the same object:
So far, we have defined
showDialog as a traditional function, what if changing it to an arrow function?
undefined, and this is because arrow functions don't have their own
this binding. Therefore, when line 15 refers to
this, it will go up and look in the outer context, which is none, so
this in line 15 gets
All functions that are managed by Vue, e.g. methods, computed functions, watchers, etc. are better to be traditional functions. This can ensure their
this always points to the current
VueComponent instance. (The binding is done by Vue when it creates the component instance.)
All right, this concludes Part 1 of this series, see you in the next section.
Here are some more articles on Vue.js: