Hello friends. Today I will continue the series about Vuejs. Specifically, I will introduce to you about Event handling in Vuejs.
- Listen to the event
- Mode of event handling
- Call inline method
- Event modifier
- Key modifier
- Why listen for events in HTML
Listen to the event
We can use the v-on
directive to listen for DOM events and execute JavaScript when these events are triggered. For example:
1 2 3 4 5 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">id</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> example-1 <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> counter += 1 <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> Đếm cừu <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> p</span> <span class="token punctuation">></span></span> {{ counter }} con cừu. <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> p</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
1 2 3 4 5 6 7 | <span class="token keyword">var</span> example1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vue</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> el <span class="token punctuation">:</span> <span class="token string">'#example-1'</span> <span class="token punctuation">,</span> data <span class="token punctuation">:</span> <span class="token punctuation">{</span> counter <span class="token punctuation">:</span> <span class="token number">0</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> |
Mode of event handling
In fact, the logic for handling events is often more complex, so it is not feasible to include JavaScript directly in the v-on
property’s value. That’s why v-on
can also get the name of a method you want to call. For example:
1 2 3 4 5 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">id</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> example-2 <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token comment"><!-- `greet` is the name of a method defined below --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> greet <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> Chào mừng <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <span class="token keyword">var</span> example2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vue</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> el <span class="token punctuation">:</span> <span class="token string">'#example-2'</span> <span class="token punctuation">,</span> data <span class="token punctuation">:</span> <span class="token punctuation">{</span> name <span class="token punctuation">:</span> <span class="token string">'Vue.js'</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token comment">// define methods under the `methods` object</span> methods <span class="token punctuation">:</span> <span class="token punctuation">{</span> greet <span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> event <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// `this` inside methods points to the Vue instance</span> <span class="token function">alert</span> <span class="token punctuation">(</span> <span class="token string">'Hello '</span> <span class="token operator">+</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token operator">+</span> <span class="token string">'!'</span> <span class="token punctuation">)</span> <span class="token comment">// `event` is the native DOM event</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> event <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">alert</span> <span class="token punctuation">(</span> event <span class="token punctuation">.</span> target <span class="token punctuation">.</span> tagName <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token comment">// you can invoke methods in JavaScript too</span> example2 <span class="token punctuation">.</span> <span class="token function">greet</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// => 'Hello Vue.js!'</span> |
Call inline method
Instead of binding methods directly, we can also call methods in a JavaScript statement:
1 2 3 4 5 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">id</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> example-3 <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> say( <span class="token punctuation">'</span> hi <span class="token punctuation">'</span> ) <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> Say hi <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> say( <span class="token punctuation">'</span> what <span class="token punctuation">'</span> ) <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> Say what <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
1 2 3 4 5 6 7 8 9 | <span class="token keyword">new</span> <span class="token class-name">Vue</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> el <span class="token punctuation">:</span> <span class="token string">'#example-3'</span> <span class="token punctuation">,</span> methods <span class="token punctuation">:</span> <span class="token punctuation">{</span> say <span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> message <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">alert</span> <span class="token punctuation">(</span> message <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> |
Sometimes we also want to access the original DOM event from the inline JavaScript statement. You can pass a DOM event into the method via the $event
variable:
1 2 3 4 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> warn( <span class="token punctuation">'</span> Form cannot be submitted yet. <span class="token punctuation">'</span> , $event) <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> Submit <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> |
1 2 3 4 5 6 7 8 9 10 11 | <span class="token comment">// ...</span> methods <span class="token punctuation">:</span> <span class="token punctuation">{</span> warn <span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> message <span class="token punctuation">,</span> event <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// now we have access to the native event</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> event <span class="token punctuation">)</span> <span class="token punctuation">{</span> event <span class="token punctuation">.</span> <span class="token function">preventDefault</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">alert</span> <span class="token punctuation">(</span> message <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Event modifier
In many cases, we need to call event.preventDefault()
or event.stopPropagation()
inside an event handler. While this is not difficult at all, it is better if the methods have to focus only on resolving the data logic instead of handling the DOM events.
To solve this problem, Vue provides event modifiers for v-on
. Event modfier
is a postfix for the directive, indicated by a period.
.stop
.prevent
.capture
.self
.once
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class="token comment"><!-- the click event's propagation will be stopped --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> a</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click.stop</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> doThis <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> a</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- the submit event will no longer reload the page --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> form</span> <span class="token attr-name"><span class="token namespace">v-on:</span> submit.prevent</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> onSubmit <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> form</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- modifiers can be chained --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> a</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click.stop.prevent</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> doThat <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> a</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- just the modifier --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> form</span> <span class="token attr-name"><span class="token namespace">v-on:</span> submit.prevent</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> form</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- use capture mode when adding the event listener --></span> <span class="token comment"><!-- i.e. an event targeting an inner element is handled here before being handled by that element --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click.capture</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> doThis <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> ... <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- only trigger handler if event.target is the element itself --></span> <span class="token comment"><!-- i.e. not from a child element --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click.self</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> doThat <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> ... <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
When using multiple modifiers at the same time, the join order is very important, because the code will be generated in that order. For example, @click.prevent.self
will prevent all clicks and @click.self.prevent
only prevent clicks on the element itself.
From version 2.1.4 onwards
1 2 3 | <span class="token comment"><!-- the click event will be triggered at most once --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> a</span> <span class="token attr-name"><span class="token namespace">v-on:</span> click.once</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> doThis <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> a</span> <span class="token punctuation">></span></span> |
Unlike other modifiers, which can only be used for native DOM events, the .once
modifier can also be used for component events . If you have not read about the component, you can skip it and come back later.
From version 2.3.0 onwards
Vue also provides a .passive
modifier, which corresponds to the passive
option for addEventListener
.
1 2 3 4 5 | <span class="token comment"><!-- the scroll event's default behavior (scrolling) will happen --></span> <span class="token comment"><!-- immediately, instead of waiting for `onScroll` to complete --></span> <span class="token comment"><!-- in case it contains `event.preventDefault()` --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name"><span class="token namespace">v-on:</span> scroll.passive</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> onScroll <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> ... <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
The .passive
modifier is particularly useful for improving the performance of apps on mobile devices.
Do not use .passive
and .prevent
together, because .prevent
will not take effect, and the browser may turn on the warning. Remember that .passive
tells the browser that you don’t want to prevent event default behavior.
Key modifier
When listening to keyboard events, we often have to check the key code. Vue supports adding key modifier (modifer for key code) for v-on
in these cases:
1 2 3 | <span class="token comment"><!-- only call `vm.submit()` when the `key` is `Enter` --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> input</span> <span class="token attr-name"><span class="token namespace">v-on:</span> keyup.enter</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> submit <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> |
Of course if you have to remember all the keys, it’s very tiring, so Vue provides alias (aliases) for the most common keys:
1 2 3 4 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> input</span> <span class="token attr-name"><span class="token namespace">v-on:</span> keyup.enter</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> submit <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> input</span> <span class="token attr-name">@keyup.enter</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> submit <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> |
The following is a complete list of key modifiers:
.enter
.tab
.delete
(used for both “Delete” and “←” keys).esc
.space
.up
.down
.left
.right
You can also define your own alias for the key modifier with the global object config.keyCodes
:
1 2 3 | <span class="token comment">// enable `v-on:keyup.f1`</span> Vue <span class="token punctuation">.</span> config <span class="token punctuation">.</span> keyCodes <span class="token punctuation">.</span> f1 <span class="token operator">=</span> <span class="token number">112</span> |
Auto key modifier
2.5.0+
You can also use any valid key name as a modifier by switching to kebab-case:
1 2 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> input</span> <span class="token attr-name">@keyup.page-down</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> onPageDown <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> |
In the above example, the onPageDown
function is only called if $event.key === 'PageDown'
.
A small number of keys ( esc
and arrow keys) have inconsistent key
values on IE9. If you need to support IE9, you should use the above alias.
System modifier keys
From version 2.1.0 onwards
You can use the following modifiers to trigger events only when the corresponding modifier keys are pressed:
.ctrl
.alt
.shift
.meta
On Macintosh keyboards, meta is the Command key (⌘). On Windows keyboards, meta is the Windows key (⊞). On the Sun Microsystems keyboard, the meta is marked with a diamond (◆). On certain keyboard types such as MIT and Lisp keyboards, the meta is labeled “META”. On Symbolics keyboard, meta is labeled “META” or “Meta”.
For example:
1 2 3 4 5 6 | <span class="token comment"><!-- Alt + C --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> input</span> <span class="token attr-name">@keyup.alt.67</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> clear <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token comment"><!-- Ctrl + Click --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">@click.ctrl</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> doSomething <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> Do something <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
The modifier keys behave differently than normal keys, and when used with a keyup
event, the modifier key must be pressed when the event is fired. In other words, keyup.ctrl
will only be activated when you release a key while pressing ctrl
. This event will not be triggered if you just release the ctrl
key alone.
Modifier .exact
2.5.0+
The .exact
(correct) modifier can be used in conjunction with other modifiers to specify that the event handler should only be executed when the correct key / mouse combination is pressed.
1 2 3 4 5 6 7 8 9 | <span class="token comment"><!-- this will fire even if Alt or Shift is also pressed --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name">@click.ctrl</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> onClick <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> A <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- this will only fire when Ctrl and no other keys are pressed --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name">@click.ctrl.exact</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> onCtrlClick <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> A <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- this will only fire when no system modifiers are pressed --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name">@click.exact</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> onClick <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> A <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> |
Modifier for mouse key
From version 2.2.0 onwards
.left
.right
.middle
These modifiers restrict processing to events triggered by a given mouse key (left, right, or middle).
Why listen to events in HTML?
You may be concerned that the entire event listener by placing the event listener in HTML like this violates the ” separation of concerns ” rule. Rest assured, since all of Vue’s event handling functions and expressions are strictly bound to the ViewModel, there will be no maintenance difficulties. In fact, using v-on
has the following benefits:
- Make locating the processing function in JavaScript code easier by skimming the HTML template.
- Because not manually attaching event handlers in JavaScript, the code in the ViewModel becomes pure logic and independent of the DOM. This makes it easier to write tests.
- When a ViewModel is destroyed, all attached event handlers are automatically removed without you having to clean up.
Here I have introduced you to Event handling and some basic concepts in Event handling VueJs. If you have any questions, please leave a comment below.