vue中的事件修饰符.self、.capture和.passive

vue中的事件修饰符有6种:

  • .stop
  • .prevent
  • .capture
  • .once
  • .self
  • .passive

.stop是stopPropagation停止冒泡,
.prevent是preventDefault阻止默认事件,
.once是点击事件将只会触发一次

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
1、.self

只在目标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和区域3中的事件是在冒泡阶段触发的

那么我们点击触发区域2呢?

可以看到打印出的情况,这时区域2中的.self修饰符事件也触发了。因为我们的目标对象是区域2。
2、.capture

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 只会阻止对元素自身的点击。

3、.passive

汉语意思:被动的,消极的;被动语态的
.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>

打印结果如下:

注意一点:默认事件在冒泡事件之后执行

如果加上.passive就会发现执行顺序发生了变化。

passive的作用是事件的默认行为立即执行(不用去查看有没有阻止默认事件的行为了),而且无需等待事件回调执行完毕。

<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.passive="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>

打印结果如下:
在这里插入图片描述
对比上面的例子,发现42比41提前打印了。

使用.passive修饰符的原因:

浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时,才能知道内部是否会调用preventDefault函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿

通俗点说就是每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。

这里一般用在滚动监听,@scoll,@touchmove 。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询prevent会使滑动卡顿。我们通过passive将内核线程查询跳过,可以大大提升滑动的流畅度。

注:passive和prevent冲突,不能同时绑定在一个监听器上。

最后我们来看一下修饰符的组合使用

以.prevent.self和.self.prevent为例
官网上说
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
1、prevent.self

<div @click="log(1)">
      区域1
      <a href="/#a" @click.prevent.self="log(2)">
         区域2
        <div @click="log(3)">区域3</div>
      </a>
</div>

点击区域3,会打印出 3,1。不但阻止了log(2),还阻止了a的默认跳转。
因为点击的时候会先prevent,阻止默认事件,阻止了跳转;然后判断是否是self,因为点击到的是区域3,所以不是self,阻止了log(2)。

2、self.prevent

<div @click="log(1)">
      区域1
      <a href="/#a" @click.self.prevent="log(2)">
         区域2
        <div @click="log(3)">区域3</div>
      </a>
</div>

点击区域3,会打印出3,1,跳转到/#a。只阻止了log(2)。

因为会先判断self,点击到区域3,self是区域3,区域2不是self,所以不会执行self事件,self事件后面紧跟着是prevent,self都不执行了,所以prevent也不会执行了,就不会执行 阻止默认事件和log(2) 。所以默认事件是可以执行的,可以跳转。
参考文章:Vue事件修饰符(二).prevent .passive

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值