The v-on directive can be used to listen for DOM events such as click
, change
, mouseover
, mouseout
, keyup
, etc.
Events are specified as an argument of the v-on
directive, e.g. v-on:click
:
<button v-on:click="correct = wordB == answer">Check answer</button>
The syntax for specifying arguments for a directive is always: v-directive:argument
Inline handlers
One type of value you can specify for v-on is an inline JavaScript expression. For example, in the above code, the expression is correct = wordB == answer
.
Multiple expressions can be separated by a semi-colon, for example:
<button v-on:click='correct = wordB == answer; showFeedback = true'>Check answer</button>
Method handlers
When the task at hand calls for multiple statements, it makes sense to move the statements to their own function which can then be invoked from the event listener.
Such functions can be defined in a methods option in your Vue options:
const FlashWord = {
data() {
return {
wordA: 'hola',
wordB: 'hello',
answer: '',
correct: null,
showFeedback: false,
}
},
methods: {
checkAnswer() {
// The keyword `this` is used to access properties from our data option
this.correct = this.wordB == this.answer;
this.showFeedback = true;
}
}
}
Our new checkAnswer function can now be invoked from the v-on:click:
<button v-on:click='checkAnswer()'>Check answer</button>
Observations:
- When we’re referencing our data options from within our methods, we had to use the this keyword (e.g.
this.correct = this.wordB == this.answer;
). This step was not necessary when accessing these same options within our template. - While not necessary in the above example, methods can be defined with parameters and accept arguments.
So far, we’ve studied two Vue options: data and methods. Later, we’ll add additional options, and it can be useful to be consistent in the order in which we set these options.
Refer to the Vue style guide’s suggestions on options order for guidance on this.
Event argument
Details about the DOM event can be accessed like so:
<button v-on:click='checkAnswer($event)'>Check answer</button>
const FlashWord = {
// [...data options redacted for brevity...]
methods: {
checkAnswer(event) {
// Demonstrating accessing info about the DOM event
console.log(event);
this.correct = this.wordB == this.answer;
this.showFeedback = true;
}
}
}
Modifiers
Some directives, including v-on, can also accept modifiers following this syntax:
v-directive:argument.modifier
For example, the keyup event listener can accept a key modifier to indicate which specific key (e.g. enter, shift, tab) it should listen for.
Using this technique, we could make it possible to submit an answer by hitting the enter key right after the user types in their guess:
<input type='text' v-model='answer' v-on:keyup.enter='checkAnswer()'>
<button v-on:click='checkAnswer()'>Check answer</button>
Vue supports all the standard JS keyboard events, you just need to specify them in lower-kebab-case.
Examples:
-
CapsLock
iscaps-lock
-
Shift
isshift
-
PageDown
ispage-down
- Etc.
v-on shorthand syntax @
The v-on directive is one of those directives you’ll use frequently, so a syntax shorthand exists to abbreviate it. Instead of writing v-on, you can use the @
symbol.
Example:
<input type='text' v-model='answer' v-on:keyup.enter='checkAnswer()'>
<button @click='checkAnswer()'>Check answer</button>
Either style is acceptable in your projects, but per the Vue style guide, it’s suggested that you are consistent with your usage of shorthands.
A shift in convention
The v-on directive looks very similar to how one might trigger a JavaScript method using plain JavaScript and a DOM on-event handler.
Example:
<button onclick='checkAnswer()'>Check answer</button>
When learning to write front-end JavaScript, we’re often taught this is bad because it breaks separation of concerns by mixing JavaScript (interactivity) into our HTML (display).
Instead, we were taught to set up an event listener in our JavaScript— something like this:
document.querySelector('button').addEventListener('click', checkAnswer);
The perspective on this has changed, though, in frameworks such as Vue, where we want the JavaScript to be declarative and data-driven, with a de-emphasis on direct interaction with the DOM.