Event Handling

    We can use the directive, which we typically shorten to the @ symbol, to listen to DOM events and run some JavaScript when they’re triggered. The usage would be v-on:click="methodName" or with the shortcut, @click="methodName"

    For example:

    1. Vue.createApp({
    2. data() {
    3. return {
    4. counter: 1
    5. }
    6. }
    7. }).mount('#basic-event')

    Result:

    See the Pen Event handling: basic by Vue () on CodePen.

    Method Event Handlers

    The logic for many event handlers will be more complex though, so keeping your JavaScript in the value of the v-on attribute isn’t feasible. That’s why v-on can also accept the name of a method you’d like to call.

    For example:

    1. <div id="event-with-method">
    2. <!-- `greet` is the name of a method defined below -->
    3. <button @click="greet">Greet</button>
    4. </div>
    1. Vue.createApp({
    2. data() {
    3. return {
    4. name: 'Vue.js'
    5. }
    6. },
    7. methods: {
    8. greet(event) {
    9. // `this` inside methods points to the Vue instance
    10. alert('Hello ' + this.name + '!')
    11. // `event` is the native DOM event
    12. if (event) {
    13. alert(event.target.tagName)
    14. }
    15. }
    16. }
    17. }).mount('#event-with-method')

    Result:

    See the Pen Event handling: with a method by Vue () on CodePen.

    Instead of binding directly to a method name, we can also use methods in an inline JavaScript statement:

    1. <button @click="say('hi')">Say hi</button>
    2. <button @click="say('what')">Say what</button>
    3. </div>

    Result:

    See the Pen by Vue (@Vue) on .

    1. <button @click="warn('Form cannot be submitted yet.', $event)">
    2. Submit
    3. </button>
    1. // ...
    2. methods: {
    3. warn(message, event) {
    4. if (event) {
    5. event.preventDefault()
    6. }
    7. alert(message)
    8. }
    9. }

    Event Modifiers

    It is a very common need to call event.preventDefault() or event.stopPropagation() inside event handlers. Although we can do this easily inside methods, it would be better if the methods can be purely about data logic rather than having to deal with DOM event details.

    To address this problem, Vue provides event modifiers for v-on. Recall that modifiers are directive postfixes denoted by a dot.

    • .stop
    • .prevent
    • .capture
    • .self
    • .once
    • .passive
    1. <!-- the click event's propagation will be stopped -->
    2. <a @click.stop="doThis"></a>
    3. <!-- the submit event will no longer reload the page -->
    4. <form @submit.prevent="onSubmit"></form>
    5. <!-- modifiers can be chained -->
    6. <a @click.stop.prevent="doThat"></a>
    7. <!-- just the modifier -->
    8. <form @submit.prevent></form>
    9. <!-- use capture mode when adding the event listener -->
    10. <!-- i.e. an event targeting an inner element is handled here before being handled by that element -->
    11. <div @click.capture="doThis">...</div>
    12. <!-- i.e. not from a child element -->
    13. <div @click.self="doThat">...</div>

    TIP

    Order matters when using modifiers because the relevant code is generated in the same order. Therefore using @click.prevent.self will prevent all clicks while @click.self.prevent will only prevent clicks on the element itself.

    1. <!-- the click event will be triggered at most once -->
    2. <a @click.once="doThis"></a>

    Unlike the other modifiers, which are exclusive to native DOM events, the .once modifier can also be used on . If you haven’t read about components yet, don’t worry about this for now.

    Vue also offers the .passive modifier, corresponding to addEventListener‘s passive option.

    The .passive modifier is especially useful for improving performance on mobile devices.

    TIP

    Don’t use .passive and together, because .prevent will be ignored and your browser will probably show you a warning. Remember, .passive communicates to the browser that you don’t want to prevent the event’s default behavior.

    When listening for keyboard events, we often need to check for specific keys. Vue allows adding key modifiers for v-on or @ when listening for key events:

    1. <!-- only call `vm.submit()` when the `key` is `Enter` -->
    2. <input @keyup.enter="submit" />

    You can directly use any valid key names exposed via as modifiers by converting them to kebab-case.

    1. <input @keyup.page-down="onPageDown" />

    Vue provides aliases for the most commonly used keys:

    • .enter
    • .tab
    • .delete (captures both “Delete” and “Backspace” keys)
    • .esc
    • .space
    • .up
    • .down
    • .left
    • .right

    System Modifier Keys

    You can use the following modifiers to trigger mouse or keyboard event listeners only when the corresponding modifier key is pressed:

    • .ctrl
    • .alt
    • .shift
    • .meta

    Note

    On Macintosh keyboards, meta is the command key (⌘). On Windows keyboards, meta is the Windows key (⊞). On Sun Microsystems keyboards, meta is marked as a solid diamond (◆). On certain keyboards, specifically MIT and Lisp machine keyboards and successors, such as the Knight keyboard, space-cadet keyboard, meta is labeled “META”. On Symbolics keyboards, meta is labeled “META” or “Meta”.

    For example:

    1. <!-- Alt + Enter -->
    2. <input @keyup.alt.enter="clear" />
    3. <!-- Ctrl + Click -->
    4. <div @click.ctrl="doSomething">Do something</div>

    TIP

    Note that modifier keys are different from regular keys and when used with keyup events, they have to be pressed when the event is emitted. In other words, keyup.ctrl will only trigger if you release a key while holding down ctrl. It won’t trigger if you release the ctrl key alone

    The .exact modifier allows control of the exact combination of system modifiers needed to trigger an event.

    1. <!-- this will fire even if Alt or Shift is also pressed -->
    2. <button @click.ctrl="onClick">A</button>
    3. <!-- this will only fire when Ctrl and no other keys are pressed -->
    4. <button @click.ctrl.exact="onCtrlClick">A</button>
    5. <!-- this will only fire when no system modifiers are pressed -->
    6. <button @click.exact="onClick">A</button>
    • .left
    • .right
    • .middle

    These modifiers restrict the handler to events triggered by a specific mouse button.

    You might be concerned that this whole event listening approach violates the good old rules about “separation of concerns”. Rest assured - since all Vue handler functions and expressions are strictly bound to the ViewModel that’s handling the current view, it won’t cause any maintenance difficulty. In fact, there are several benefits in using or @:

    1. It’s easier to locate the handler function implementations within your JS code by skimming the HTML template.