事件处理
快速入门
在 Vue 中如果要给元素绑定事件,可以使用内置指令 v-on,使用该指定就可以绑定事件:
vue
<template>
<div>{{ count }}</div>
<button v-on:click="add">+1</button>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
function add() {
count.value++;
}
</script>
<style scoped></style>
上面的事件示例非常简单,不过关于事件处理,有各种各样的细节。
事件处理各种细节
事件内联语句
- 如果事件相关的处理比较简单,那么可以将事件处理器写成内连的
vue
<template>
<div>{{ count }}</div>
<button v-on:click="count++">+1</button>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
</script>
<style scoped></style>
这种内连事件处理器用的比较少,仅在逻辑比较简单的时候可以快速完成事件的书写。
事件 v-bind 简写
- 绑定事件是一个很常见的需求,因此 Vue 也提供了简写形式,通过 @ 符号就可以绑定事件
vue
<button @click="count++">+1</button>
在日常开发中,更多的见到的就是简写形式。
事件传参
- 向事件处理器传递参数
vue
<template>
<div>{{ count }}</div>
<button @click="add('Hello World')">+1</button>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
function add(message) {
count.value++;
console.log(message);
}
</script>
<style scoped></style>
事件对象
- 事件对象
- 没有传参:事件对象会作为一个额外的参数,自动传入到事件处理器,在事件处理器中,只需要在形参列表中声明一下即可
- 如果有传参:这种情况下需要使用一个特殊的变量 $event 来向事件处理器传递事件对象
vue
<template>
<div>{{ count }}</div>
<button @click="add">+1</button>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
// 事件对象会自动传入,直接在事件处理器的形参中声明即可
function add(event) {
count.value++;
console.log(event);
console.log(event.target);
console.log(event.clientX, event.clientY);
}
</script>
<style scoped></style>
vue
<template>
<div>{{ count }}</div>
<!-- 必须显式的使用 $event 来向事件处理器传递事件对象 -->
<button @click="add('Hello World', $event)">+1</button>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
function add(message, event) {
count.value++;
console.log(message);
console.log(event);
console.log(event.target);
console.log(event.clientX, event.clientY);
}
</script>
<style scoped></style>
如果是箭头函数,写法如下:
vue
<template>
<div>{{ count }}</div>
<!-- 如果是箭头函数,那么事件对象需要作为参数传入 -->
<!-- 此时参数没有必须是 $event 的限制了 -->
<button @click="(event) => add('Hello World', event)">+1</button>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
function add(message, event) {
count.value++;
console.log(message);
console.log(event);
console.log(event.target);
console.log(event.clientX, event.clientY);
}
</script>
<style scoped></style>
事件修饰符
之所以会有修饰符,是因为之前在书写原生事件处理的时候,事件处理器中经常会包含诸如阻止冒泡、阻止默认事件等非事件业务的逻辑。有了修饰符之后,可以使用事件修饰符来完成这些非核心的业务处理,让事件处理器更加专注于业务逻辑。
常见的事件处理器:
- .stop:阻止事件冒泡
- .prevent:阻止默认行为
- .self:只有事件在该元素本身上触发时才触发处理函数(不是在子元素上)
- .capture:改变事件的触发方式,使其在捕获阶段而不是冒泡阶段触发。
- .once:事件只触发一次
- .passive:用于提高页面滚动的性能。
修饰符的使用也很简单:
vue
<button @click.stop="handleClick">点击我</button>
下面是一个具体的示例:
vue
<template>
<button @click.once="clickHandle">click</button>
</template>
<script setup>
function clickHandle() {
console.log("你触发了事件");
}
</script>
<style scoped></style>
另外需要说一下,事件修饰符是可以连用的,例如现在有这么一个需求,我们希望用户在点击按钮时:
- 阻止事件冒泡(.stop)。
- 阻止默认行为(.prevent),例如,防止表单提交。
- 在捕获阶段触发事件处理器(.capture),确保在任何可能的冒泡前响应。
- 事件处理器只触发一次(.once)。
vue
<button @click.capture.stop.prevent.once>click</button>
在连用事件修饰符的时候,修饰符的顺序通常不会影响最终的行为,因为不同的修饰符代表对不同方面的行为的控制,相互是不冲突的。
除了事件修饰符以外,Vue 还提供了一组按键修饰符,按键修饰符主要是用于检查特点的按钮:
- .enter
- .tab
- .delete (捕获“Delete”和“Backspace”两个按键)
- .esc
- .space
- .up
- .down
- .left
- .right
- .ctrl
- .alt
- .shift
- .meta(不同的系统对应不同的按键)
vue
<template>
<input type="text" @keyup.enter="submitText" />
</template>
<script setup>
function submitText() {
console.log("你要提交输入的内容");
}
</script>
<style scoped></style>
按键修饰符也是能够连用,比如上面的例子,我们修改为 alt + enter 是提交
vue
<input type="text" @keyup.alt.enter="submitText" />
Mac 系统中 alt 对应的是 option 按键
有一个特殊的修饰符 .exact ,exact 该单词的含义是“精确、精准” ,该修饰符的作用在于控制触发事件的时候,必须是指定的按键组合,不能够有其他按键。
vue
<button @click.ctrl="onClick">A</button>
在上面的例子中,指定按下 ctrl 键触发事件,但是假设我现在同时按下 alt 和 ctrl 也会触发事件
vue
<button @click.ctrl.exact="onClick">A</button>
添加了 .exact 修饰符之后,表示只有在按下 ctrl 并且没有按下其他按键的时候才会触发事件
最后还有三个鼠标按键修饰符,用于指定特定的鼠标按键:
- .left
- .right
- .middle
vue
<template>
<button
class="context-menu-button"
@contextmenu.prevent.right="handleRightClick"
>
右键点击
</button>
</template>
<script setup>
function handleRightClick() {
console.log("你点击了鼠标右键");
}
</script>
<style scoped>
.context-menu-button {
padding: 10px 20px;
cursor: context-menu; /* 显示适当的鼠标指针 */
background-color: #f5f5f5;
border: 1px solid #ccc;
border-radius: 5px;
}
</style>
-EOF-