直接跳到内容

事件处理 | Event Handling

监听事件 | Listening to Events

We can use the v-on 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="handler" or with the shortcut, @click="handler".

我们可以使用 v-on 指令 (简写为 @) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript。用法:v-on:click="handler"@click="handler"

The handler value can be one of the following:

事件处理器 (handler) 的值可以是:

  1. Inline handlers: Inline JavaScript to be executed when the event is triggered (similar to the native onclick attribute).
  • 内联事件处理器:事件被触发时执行的内联 JavaScript 语句 (与 onclick 类似)。
  1. Method handlers: A property name or path that points to a method defined on the component.
  • 方法事件处理器:一个指向组件上定义的方法的属性名或是路径。

内联事件处理器 | Inline Handlers

Inline handlers are typically used in simple cases, for example:

内联事件处理器通常用于简单场景,例如:

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

方法事件处理器 | Method Handlers

The logic for many event handlers will be more complex though, and likely isn't feasible with inline handlers. That's why v-on can also accept the name or path of a component method you'd like to call.

随着事件处理器的逻辑变得愈发复杂,内联代码方式变得不够灵活。因此 v-on 也可以接受一个方法名或对某个方法的调用。

For example:

举例来说:

js
const name = ref('Vue.js')

function greet(event) {
  alert(`Hello ${name.value}!`)
  // `event` is the native DOM event
  // `event` 是 DOM 原生事件
  if (event) {
    alert(event.target.tagName)
  }
}
js
data() {
  return {
    name: 'Vue.js'
  }
},
methods: {
  greet(event) {
    // `this` inside methods points to the current active instance
    // 方法中的 `this` 指向当前活跃的组件实例
    alert(`Hello ${this.name}!`)
    // `event` is the native DOM event
    // `event` 是 DOM 原生事件
    if (event) {
      alert(event.target.tagName)
    }
  }
}
template
<!-- `greet` is the name of the method defined above -->
<!-- `greet` 是上面定义过的方法名 -->
<button @click="greet">Greet</button>

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

方法事件处理器会自动接收原生 DOM 事件并触发执行。在上面的例子中,我们能够通过被触发事件的 event.target 访问到该 DOM 元素。

See also: Typing Event Handlers

你也可以看看为事件处理器标注类型这一章了解更多。

See also: Typing Event Handlers

你也可以看看为事件处理器标注类型这一章了解更多。

方法与内联事件判断 | Method vs. Inline Detection

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.

模板编译器会通过检查 v-on 的值是否是合法的 JavaScript 标识符或属性访问路径来断定是何种形式的事件处理器。举例来说,foofoo.barfoo['bar'] 会被视为方法事件处理器,而 foo()count++ 会被视为内联事件处理器。

在内联处理器中调用方法 | Calling Methods in Inline Handlers

Instead of binding directly to a method name, we can also call methods in an inline handler. This allows us to pass the method custom arguments instead of the native event:

除了直接绑定方法名,你还可以在内联事件处理器中调用方法。这允许我们向方法传入自定义参数以代替原生事件:

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

在内联事件处理器中访问事件参数 | Accessing Event Argument in Inline Handlers

Sometimes we also need to access the original DOM event in an inline handler. You can pass it into a method using the special $event variable, or use an inline arrow function:

有时我们需要在内联事件处理器中访问原生 DOM 事件。你可以向该处理器方法传入一个特殊的 $event 变量,或者使用内联箭头函数:

template
<!-- using $event special variable -->
<!-- 使用特殊的 $event 变量 -->
<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>
js
function warn(message, event) {
  // now we have access to the native event
  // 这里可以访问原生事件
  if (event) {
    event.preventDefault()
  }
  alert(message)
}
js
methods: {
  warn(message, event) {
    // now we have access to the native event
    // 这里可以访问 DOM 原生事件
    if (event) {
      event.preventDefault()
    }
    alert(message)
  }
}

事件修饰符 | 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.

在处理事件时调用 event.preventDefault()event.stopPropagation() 是很常见的。尽管我们可以直接在方法内调用,但如果方法能更专注于数据逻辑而不用去处理 DOM 事件的细节会更好。

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

为解决这一问题,Vue 为 v-on 提供了事件修饰符。修饰符是用 . 表示的指令后缀,包含以下这些:

  • .stop
  • .prevent
  • .self
  • .capture
  • .once
  • .passive
template
<!-- 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 -->
<!-- 仅当 event.target 是元素本身时才会触发事件处理器 -->
<!-- 例如:事件处理器不来自子元素 -->
<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 click's default action on the element itself and its children, while @click.self.prevent will only prevent click's default action on the element itself.

使用修饰符时需要注意调用顺序,因为相关代码是以相同的顺序生成的。因此使用 @click.prevent.self 会阻止元素及其子元素的所有点击事件的默认行为,而 @click.self.prevent 则只会阻止对元素本身的点击事件的默认行为。

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

.capture.once.passive 修饰符与原生 addEventListener 事件相对应:

template
<!-- 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           -->
<!-- 添加事件监听器时,使用 `capture` 捕获模式 -->
<!-- 例如:指向内部元素的事件,在被内部元素处理前,先被外部处理 -->
<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()`                -->
<!-- 滚动事件的默认行为 (scrolling) 将立即发生而非等待 `onScroll` 完成 -->
<!-- 以防其中包含 `event.preventDefault()` -->
<div @scroll.passive="onScroll">...</div>

The .passive modifier is typically used with touch event listeners for improving performance on mobile devices.

.passive 修饰符一般用于触摸事件的监听器,可以用来改善移动端设备的滚屏性能

TIP

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.

请勿同时使用 .passive.prevent,因为 .passive 已经向浏览器表明了你不想阻止事件的默认行为。如果你这么做了,则 .prevent 会被忽略,并且浏览器会抛出警告。

按键修饰符 | Key Modifiers

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:

在监听键盘事件时,我们经常需要检查特定的按键。Vue 允许在 v-on@ 监听按键事件时添加按键修饰符。

template
<!-- only call `submit` when the `key` is `Enter` -->
<!-- 仅在 `key` 为 `Enter` 时调用 `submit` -->
<input @keyup.enter="submit" />

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

你可以直接使用 KeyboardEvent.key 暴露的按键名称作为修饰符,但需要转为 kebab-case 形式。

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

In the above example, the handler will only be called if $event.key is equal to 'PageDown'.

在上面的例子中,仅会在 $event.key'PageDown' 时调用事件处理。

按键别名 | Key Aliases

Vue provides aliases for the most commonly used keys:

Vue 为一些常用的按键提供了别名:

  • .enter
  • .tab
  • .delete (捕获“Delete”和“Backspace”两个按键 | 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”.

在 Mac 键盘上,meta 是 Command 键 (⌘)。在 Windows 键盘上,meta 键是 Windows 键 (⊞)。在 Sun 微机系统键盘上,meta 是钻石键 (◆)。在某些键盘上,特别是 MIT 和 Lisp 机器的键盘及其后代版本的键盘,如 Knight 键盘,space-cadet 键盘,meta 都被标记为“META”。在 Symbolics 键盘上,meta 也被标识为“META”或“Meta”。

举例来说:

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

<!-- Ctrl + Click -->
<!-- Ctrl + 点击 -->
<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.

请注意,系统按键修饰符和常规按键不同。与 keyup 事件一起使用时,该按键必须在事件发出时处于按下状态。换句话说,keyup.ctrl 只会在你仍然按住 ctrl 但松开了另一个键时被触发。若你单独松开 ctrl 键将不会触发。

.exact 修饰符 | .exact Modifier

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

.exact 修饰符允许精确控制触发事件所需的系统修饰符的组合。

template
<!-- this will fire even if Alt or Shift is also pressed -->
<!-- 当按下 Ctrl 时,即使同时按下 Alt 或 Shift 也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- this will only fire when Ctrl and no other keys are pressed -->
<!-- 仅当按下 Ctrl 且未按任何其他键时才会触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- this will only fire when no system modifiers are pressed -->
<!-- 仅当没有按下任何系统按键时触发 -->
<button @click.exact="onClick">A</button>

鼠标按键修饰符 | Mouse Button Modifiers

  • .left
  • .right
  • .middle

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

这些修饰符将处理程序限定为由特定鼠标按键触发的事件。

事件处理 | Event Handling已经加载完毕