Vue3手册译稿 - 基础 - 事件处理
事件处理
事件监听
当DOM事件被触发时,我们使用v-on
(缩写@
符号)来监听事件,运行JavaScript。使用方法为v-on:click="method"
或缩写为@click="method"
。
例如:
<div id="basic-event">
<button @click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
Vue.createApp({
data() {
return {
counter: 0
}
}
}).mount('#basic-event')
事件处理方法
因为有些事件处理比较复杂的逻辑,所以直接在v-on
后面写JavaScript是不太现实的。所以v-on
可以接受一个方法名来调用。例如:
<div id="event-with-method">
<!-- `greet`就是在下面定义的方法名 -->
<button @click="greet">Greet</button>
</div>
Vue.createApp({
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)
}
}
}
}).mount('#event-with-method')
事件方法传递参数
(感觉这个翻译靠谱点吧。原文是Methods in Inline Handlers)
<div id="inline-handler">
<button @click="say('hi')">Say hi</button>
<button @click="say('what')">Say what</button>
</div>
Vue.createApp({
methods: {
say(message) {
alert(message)
}
}
}).mount('#inline-handler')
有时候我们需要在方法中访问DOM的原生事件句柄,你可以通过$event
传递进来:
<button @click="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)
}
}
多事件处理
你可以在一个事件中调用多个用逗号分隔的方法,如下:
<!-- 按钮点击时one() 和 two() 都会执行 -->
<button @click="one($event), two($event)">
Submit
</button>
// ...
methods: {
one(event) {
// 第一个事件的业务逻辑
},
two(event) {
// 第二个事件的业务逻辑
}
}
事件修饰符
事件响应过程中经常会用到event.preventDefault()
和event.stopPropagation()
。虽然我们可以在方法里简单的调用,但最好方法完全是数据逻辑而不必去处理DOM细节。
针对这个问题,Vue提供了v-on
的修饰符。调用方法是在指令后面加一个后缀。
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止冒泡事件 -->
<a @click.stop="doThis"></a>
<!-- 表单提交不会刷新页面 -->
<form @submit.prevent="onSubmit"></form>
<!-- 修饰符可以嵌套 -->
<a @click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form @submit.prevent></form>
<!-- 事件监听使用捕获模式 -->
<!-- i.e. 穿透执行,从下向上冒呗 -->
<div @click.capture="doThis">...</div>
<!--只有事件的目标是自己才触发 -->
<!-- i.e. 不是从子元素触发的 -->
<div @click.self="doThat">...</div>
[info]提示
使用修饰符顺序问题同代码的书写顺序。因此使用@click.prevent.self
会阻止所有点击而@click.sel.prevent
只会阻止元素自身的点击。
<!-- 最多只触发一次 -->
<a @click.once="doThis"></a>
.once
不像其他修饰符只能用于原生组件,它也可以应用于组件。如果你还没有阅读过组件知识,先别烦神了。
Vue同时提供.passive
修饰符,同addEventListener
的passive
选项一样。
<!-- 滚动事件默认是触发的 -->
<!-- 替代 `onScroll` 完成-->
<!--内含 `event.preventDefault()` -->
<div @scroll.passive="onScroll">...</div>
passive
修饰符对移动端性能提升尤为有用。
[info]不要把
.passive
和.prevent
同时使用,因为prevent
会被忽略且浏览器会收到警告信息。记住,.passive
通知浏览器你不想阻止事件的默认行为。
键修饰符
我们经常需要监听键盘上特殊按键行为。Vue允许使用v-on
或@
来监听键盘的输入:
<!-- 当按下回车后会调用 `vm.submit()` -->
<input @keyup.enter="submit" />
你可以使用任意通过`keyboardEvent.key暴露出来的键名作为修饰符,只要使用驼峰命名即可。
<input @keyup.page-down="onPageDown" />
PageDown
按钮触发事件。
键别名
Vue提供了大部分常用键的别名
.enter
.tab
.delete
(同时捕获 "Delete" 和 "Backspace" 键).esc
.space
.up
.down
.left
.right
系统控制键修饰符
当相应的修饰键被按下时,你可以使用以下修饰键触发鼠标或键盘事件监听:
.ctrl
.alt
.shift
.meta
[info]mac电脑
meta
指的是命令键(⌘),Windows电脑指的是windows键(⊞)。在sun公司的微系统键盘,meta
指的是实心菱形键(◆)。在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。在符号键盘上,meta 被标记为“META”或者“Meta”。
示例:
<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
[warning] 系统控制键修饰在使用
key.up
时不同于普通键,它在按下时指令就发出了。换句话说,只有按下ctrl
释放其它键时才会触发事件,单单释放ctrl
键并不会触发事件。
.exact
修饰符
exact
修饰符控制系统组合键触发事件:
<!-- Alt或Shift键同时按下时也会执行-->
<button @click.ctrl="onClick">A</button>
<!-- 没有其他键被按下时才会执行 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!--没有系统控制键被按下时才会执行 -->
<button @click.exact="onClick">A</button>
鼠标修饰符
.left
.right
.middle
鼠标按钮修饰符会阻事件只响应鼠标特定按钮点击。
为什么在HTML中监听?
你可能注意到了所有一的事件监听貌似违反了“关键点隔离”这个好的旧规则。请放宽心,因为所有Vue的操作函数及表达式均已绑定到当前视图的ViewModel,维护起来一点也不困难。事实上使用v-on
或@
还有一些优点。
- 通过浏览HTML模板很容易定位到操作函数的JS实现代码。
- 因为你不需要再在JS代码里人工设置监听,你的ViewModel代码只需要关注纯逻辑和DOM。这也更容易进行测试。
- 当一个ViewModel被销毁,所有的事件监听也会移除。不需要再手工清除。