vue中的事件修饰符有6种:
.stop是stopPropagation停止冒泡,
.prevent是preventDefault阻止默认事件,
.once是点击事件将只会触发一次
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
只在目标Dom是绑定了动作的Dom才触发
也就是说只有这个Dom绑定了这个事件,且触发的dom是这个目标dom,才会触发这个事件。**
实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>.self修饰符</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id='app'>
<div @click="log('11')" @click.self="log('12')" style="background-color: aqua; height: 400px; width: 400px;">
<div @click="log('21')" @click.self="log('22')" style="background-color: #2195de; height: 200px; width: 400px;">
<div @click.prevent="log('31')" @click.self="log('32')" style="background-color: #9521de; height: 100px; width: 400px;color:#fff;line-height: 100px;text-align: center;">事件修饰符探索</div>
</div>
</div>
</div>
<script>
var app = new Vue({
el:"#app",
methods:{
log(value){
console.log(value)
}
}
})
</script>
</body>
</html>
可以看到有三块区域:1是最外层,2是第二层,3是最里层。
1包栝2和3,2包括3
那么我点击区域3,打印出:
先触发的是区域3中的.prevent和.self修饰符事件,然后是区域2中的点击事件,但是.self事件没有触发,最后是区域1中的点击事件,同样.self事件没有触发。因为我们的目标DOM是区域3,所以触发的是区域3中的.self。
我们注意到区域2和区域3都是在事件冒泡阶段触发的,这个一定要注意,因为跟下面要讲解的.capture有关。
如果.prevent改为.stop,那么区域2和3的点击事件是不会触发的。
那么我们点击触发区域2呢?
可以看到打印出的情况,这时区域2中的.self修饰符事件也触发了。因为我们的目标对象是区域2。
capture汉语意思:捕获
主要是在事件的捕获阶段触发父级元素的事件。
刚才在上面的.self的例子中我们说了目标元素的外层元素的事件是在事件冒泡阶段触发的。那如果加上.capture修饰符,就会在事件的捕获阶段触发。
实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>.self修饰符</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id='app'>
<div @click.capture="log('11')" @click="log('12')" @click.self="log('13')" style="background-color: aqua; height: 400px; width: 400px;">
<div @click.capture="log('21')" @click="log('22')" @click.self="log('23')" style="background-color: #2195de; height: 200px; width: 400px;">
<div @click.stop="log('31')" @click.self="log('32')" style="background-color: #9521de; height: 100px; width: 400px;color:#fff;line-height: 100px;text-align: center;">事件修饰符探索</div>
</div>
</div>
</div>
<script>
var app = new Vue({
el:"#app",
methods:{
log(value){
console.log(value)
}
}
})
</script>
</body>
</html>
我们点击区域3,可以看到
这里发现先触发了区域1和2中的事件,然后再到区域3中的事件。
说明加上.capture修饰符是在捕获阶段触发了事件。
因为设置了stop所以冒泡阶段的事件没有触发,没有打印出22,12,如果不加stop,会打印出22,12的
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
汉语意思:被动的,消极的;被动语态的
.passive 会告诉浏览器你不想阻止事件的默认行为
prevent 是拦截默认事件,passive是不拦截默认事件。
passive这个修饰符会执行默认方法。你们可能会问,明明默认执行为什么会设置这样一个修饰符。这就要说一下这个修饰符的本意了。
某些标签拥有自身的默认事件,如a[href="#"],button[type=“submit”] 这种标签在冒泡结束后会开始执行默认事件。注意默认事件虽然是冒泡后开始,但不会因为stop阻止事件传递而停止。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>.self修饰符</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id='app'>
<div @click.capture="log('11')" @click="log('12')" @click.self="log('13')" style="background-color: aqua; height: 400px; width: 400px;">
<div @click.capture="log('21')" @click="log('22')" @click.self="log('23')" style="background-color: #2195de; height: 200px; width: 400px;">
<div @click.capture.stop="log('31')" @click.self="log('32')" style="background-color: #9521de; height: 100px; width: 400px;color:#fff;line-height: 50px;text-align: center;">
<a @click="log('41')" href="javascript: console.log('默认事件')" style="display: block;height: 50px;width: 4oopx;background-color: red;">点击a标签</a>
</div>
</div>
</div>
</div>
<script>
var app = new Vue({
el:"#app",
methods:{
log(value){
console.log(value)
}
}
})
</script>
</body>
</html>
点击a标签,打印的数据如下:
因为在代码中写了@click.capture.stop="log(‘31’)"这一行,所以第三次捕获后终止事件传递,没有打印41,但不会阻止默认事件。
上面的代码进行了一些改动,如下:
<div id='app'>
<div @click.capture="log('11')" @click="log('12')" @click.self="log('13')" style="background-color: aqua; height: 400px; width: 400px;">
<div @click.capture="log('21')" @click="log('22')" @click.self="log('23')" style="background-color: #2195de; height: 200px; width: 400px;">
<div @click.capture="log('31')" @click="log('32')" @click.self="log('33')" style="background-color: #9521de; height: 100px; width: 400px;color:#fff;line-height: 50px;text-align: center;">
<a @click="log('41')" @click.capture="log('42')" href="javascript: console.log('默认事件')" style="display: block;height: 50px;width: 4oopx;background-color: red;">点击a标签</a>
</div>
</div>
</div>
</div>
浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时,才能知道内部是否会调用preventDefault函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿
通俗点说就是每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。
这里一般用在滚动监听,@scoll,@touchmove 。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询prevent会使滑动卡顿。我们通过passive将内核线程查询跳过,可以大大提升滑动的流畅度。
注:passive和prevent冲突,不能同时绑定在一个监听器上。
参考文章:Vue事件修饰符(二).prevent .passive