Luna Tech

Tutorials For Dummies.

Vue: Event Handling

2022-03-20


0. Intro

Reference

Syntax: v-on:click="handler" or @click="handler"

可以用于两种情况:

  1. inline handler: Inline JavaScript to be executed when the event is triggered,类似 native onclick attribute
  2. method handler:A property name or path that points to a method defined on the component.

1. Inline Handlers - 适用于简单的情况

<button @click="count++">Add 1</button>
<p>Count is: {{ count }}</p>
data() {
  return {
    count: 0
  }
}

2. Method Handlers - logic 复杂的情况

method handler 会自动接收到 trigger event 的 DOM Event object。

A method handler automatically receives the native DOM Event object that triggers it - in the example below, we are able to access the element dispatching the event via event.target.tagName.

<!-- `greet` is the name of the method defined above -->
<button @click="greet">Greet</button>
data() {
  return {
    name: 'Vue.js'
  }
},
methods: {
  greet(event) {
    // `this` inside methods points to the current active instance
    alert(`Hello ${this.name}!`)
    // `event` is the native DOM event
    if (event) {
      alert(event.target.tagName)
    }
  }
}

3. Method vs. Inline Detection

Q:Compiler 怎么知道 @click="abc"的 abc 是个 data property 还是个 method? A:Compiler 会通过 check v-on value string 是否是一个有效的 JS identifier 或者 property access path 来 detect method handler。

The template compiler detects method handlers by checking whether the v-on value string is a valid JavaScript identifier or property access path. For example, foo, foo.bar and foo['bar'] are treated as method handlers, while foo() and count++ are treated as inline handlers.


4. Calling Methods in Inline Handlers

我们除了可以 bind method name 之外,还可以 call method in inline handler,这样我们可以 pass custom arguments to the method instead of the native event.

Example

<button @click="say('hello')">Say hello</button>
<button @click="say('bye')">Say bye</button>
methods: {
  say(message) {
    alert(message)
  }
}

5. Accessing Event Argument in Inline Handlers

假如我们需要在 inline handler 里面 access original DOM event,可以通过 $event variable 来传入 method,或者使用 arrow function。

Example

<!-- using $event special variable -->
<button @click="warn('Form cannot be submitted yet.', $event)">Submit</button>

<!-- using inline arrow function -->
<button @click="(event) => warn('Form cannot be submitted yet.', event)">
  Submit
</button>
methods: {
  warn(message, event) {
    // now we have access to the native event
    if (event) {
      event.preventDefault()
    }
    alert(message)
  }
}

6. Event Modifiers

为什么要在 event handler 里面用 event.preventDefault()event.stopPropagation()

reference

JS 有两种事件传播模式,一种是 capturing/trickling(捕获/滴流),一种是 bubbling(冒泡)。

capturing 是自上而下,bubbling 是自下而上。

两种模式的区别在于,决定 DOM element 接收事件的顺序,从而决定 event handler 被触发的顺序。

如何定义模式?

addEventListener(type, listener, useCapture) 第三个参数是 true 表明使用 capturing 模式,默认为 bubbling。

preventDefault 用来干嘛?

假如我们想要阻止当前 element 的默认特性(比如 href 会默认跳到链接里面),我们就要用 preventDefault。

stopPropagation 用来干嘛?

假如我们只想触发当前 element,不想去传播事件,就用这个。

Vue 里面如何使用这两个 function?

我们可以直接在 v-on 里面加上这个 event modifier,就不用在 handler 里面做这件事了,代码更简洁。

modifier 就是 directive postfixes denoted by a dot.

Reference

Note: 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.

Note2: Do not use .passive and .prevent together, because .passive already indicates to the browser that you do not intend to prevent the event’s default behavior, and you will likely see a warning from the browser if you do so. 一起使用的时候 .prevent 会被忽略。

Example

<!-- the click event's propagation will be stopped -->
<a @click.stop="doThis"></a>

<!-- the submit event will no longer reload the page -->
<form @submit.prevent="onSubmit"></form>

<!-- modifiers can be chained -->
<a @click.stop.prevent="doThat"></a>

<!-- just the modifier -->
<form @submit.prevent></form>

<!-- only trigger handler if event.target is the element itself -->
<!-- i.e. not from a child element -->
<div @click.self="doThat">...</div>

The .capture, .once, and .passive modifiers mirror the options of the native addEventListener method:

<!-- use capture mode when adding the event listener -->
<!-- i.e. an event targeting an inner element is handled here before being handled by that element -->
<div @click.capture="doThis">...</div>

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

<!-- the scroll event's default behavior (scrolling) will happen -->
<!-- immediately, instead of waiting for `onScroll` to complete  -->
<!-- in case it contains `event.preventDefault()`                -->
<div @scroll.passive="onScroll">...</div>

7. Key Modifiers

我们可以监听 keyboard 按键。

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

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

<!-- only call `vm.onPageDown()` when the `key` is `PageDown` -->
<input @keyup.page-down="onPageDown" />

常用 key

我们还可以加上其他的 modifier,也就是定义组合键:

Example

<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

.exact modifier - 多一个不行,少一个也不行

<!-- this will fire even if Alt or Shift is also pressed -->
<button @click.ctrl="onClick">A</button>

<!-- this will only fire when Ctrl and no other keys are pressed -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- this will only fire when no system modifiers are pressed -->
<button @click.exact="onClick">A</button>

8. Mouse Button Modifiers