vue3.js 事件处理详解
一、事件处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<button @click="num--">-</button>
{{num}}
<button @click="num++">+</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm = Vue.createApp({
data() {
return {
num: 100
}
}
});
vm.mount('#app');
</script>
</body>
</html>
注意:“v-on” 可以使用 “@” 代替,他们的作用一样的,根据自己的习惯进行选择。
二、事件修饰符
对事件可以添加一些通用的限制,如阻止事件冒泡,在 vue 中,对事件的限制提供的特定写法,叫做修饰符
v-on:事件.修饰符
@事件.修饰符
主要修饰符有:
- stop:等同于 javascript 中的 event.stopPropagation(),阻止事件冒泡;
- prevent:等同于 javascirpt 中的 event.preventDefault(),阻止默认事件的发生;
- capture:与事件冒泡的方向相反,事件捕获由外到内;
- self:只会触发自己范围内的事件
- once:只会触发一次;
- passive:执行默认行为
- stop
stop 修饰符用来阻止事件冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div @click="outside">
<div @click.stop="inside">阻止事件冒泡</div>
</div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm = Vue.createApp({
methods: {
outside: function() {
console.log('外');
},
inside: function() {
console.log('内');
}
}
});
vm.mount('#app');
</script>
</body>
</html>
不加 stop 修饰符会输出内外两个 console.log,加了只会输出内部的 console.log
- capture
事件捕获模式与事件冒泡模式是一对相反的事件处理流程,若在父级元素上使用 capture 修饰符,则事件由外而内触发。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div @click.capture="outside">
外
<div @click.capture="center">
中
<div @click="inside">内</div>
</div>
</div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm = Vue.createApp({
methods: {
outside: function() {
console.log('外');
},
center() {
console.log('中');
},
inside: function() {
console.log('内');
}
}
});
vm.mount('#app');
</script>
</body>
</html>
点击 “内” 节点,日志输出顺序会是 :外 –> 中 –> 内
- self
self 修饰符可以理解为跳过冒泡和捕获事件,只有直接作用在该元素上的事件才可以执行。self 修饰符会监视事件是否作用在元素上,若不是,则冒泡跳过该元素。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div @click="outside">
外
<div @click.self="center">
中
<div @click="inside">内</div>
</div>
</div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm = Vue.createApp({
methods: {
outside: function() {
console.log('外');
},
center() {
console.log('中');
},
inside: function() {
console.log('内');
}
}
});
vm.mount('#app');
</script>
</body>
</html>
点击 “内” 节点,日志输出顺序会是 :内 –> 外
- once
有些需求只要执行一次操作,比如微信朋友圈点赞功能,就可以采用 once 修饰符
@click.once="clickFn"
- prevent
prevent 修饰符用于阻止默认行为,比如 <a> 标签,点击时,会触发默认的跳转行为
<a @click="clickFn" href="https://www.ifrontend.net/">阻止默认跳转行为</a>
- passive
明明默认执行的行为,为什么还要使用 passive 修饰符呢?原因是浏览器只有等内核线程执行到事件监听器对应的 javacript 代码时,才能知道内部是否会调用 preventDefault 函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化。这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿。
通俗的说就是每次事件产生时,浏览器都会去查询一下是否有 preventDefault 阻止该次事件的默认动作。加上 passive 修饰符就是为了告诉浏览器,不用查询了,没用 preventDefault 阻止默认行为。
passive 修饰符一般用在滚动监听、@scoll 和 @touchmove 中。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询 prevent 会使滑动卡顿。通过 passive 修饰符将内核线程查询路过,可以大大提升滑动的流畅度。
使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生。因此,使用 v-on:click.prevent.self 会阻止所有的单击,而 v-on:click.self.prevent 只会阻止对元素自身身的单击。
- 按键修饰符
keydown:键盘按键按下时触发
keyup:键盘按键抬起时触发
keypress: 键盘按键按下时抬起间隔期间触发
常用按键码别名:
- .enter
- .tab
- .delete
- .esc
- .space
- .up
- .down
- .left
- .right
@keydown.enter="fn"
@keyup.enter="fn"
@keypress.enter="fn"
- 系统修饰符
可以用如下修饰符来实现仅在按下相应键时才触发鼠标或键盘事件监听器。
- .ctrl
- .alt
- .shift
- .meta
系统修饰符与常规按键不同,在和 keyup 事件一起使用时,事件触发时修饰符必须外于按下状态,只有按住 Ctrl 的情况下释放其它按键,才能触发 keyup.ctrl
@keyup.shift.enter="fn"