理解vue的几种事件修饰符和原生js事件冒泡

168 阅读3分钟

最近在使用Element组件的时候,遇到了列表内图片点击预览触发列的点击事件问题;其实就是事件的冒泡和捕捉,就整理了一下vue内的事件修饰符,为记录也为避个坑。

1、native

子组件:
<div style="border: 1px solid rgb(24, 19, 19); height: 100px;width: 100px;">
 <button @click="onChildClick">ChildClick</button>
</div>
父组件
<Child @click="onChildClick"></Child>

如果我们直接在Child上定义事件,在vue2是无法触发的。这个时候就需要加上native,这个是因为对于子组件中未被定义的事件,是通过this.$emit才能触发的,所以要想实现这个效果需要将原生 DOM 监听器添加到子组件的根元素中。

父组件
<Child @click.native="onChildClick"></Child>

当然vue3已经去掉了.native修饰符。新增的 emits 选项允许子组件定义真正会被触发的事件。 因此,对于子组件中未被定义为组件触发的所有事件监听器,Vue 现在将把它们作为原生事件监听器添加到子组件的根元素中 (除非在子组件的选项中设置了 inheritAttrs: false)。

image.png

2、vue2提供的常见修饰符如下: stop once self capture prevent

stop: 阻止事件冒泡

    <ul @click="onUlClick">
      <li @click="onLiClick">one</li>
      <li @click="onLiClick">two</li>
    </ul>
    // 如果我们点击li事件,也会触发ul的事件,这个就是冒泡引起的。
    
    <ul @click="onUlClick">
      <li @click.stop="onLiClick">one</li>
      <li @click="onLiClick">two</li>
    </ul>
    // 如果我们加上.stop修饰符,就会阻止冒泡不会触发ul的事件。

once: 事件只执行一次

    <ul @click="onUlClick">
      <li @click.once="onLiClick">one</li>
      <li @click="onLiClick">two</li>
    </ul>
    // 如果我们点击li事件,它只会触发一下,但是再次点击也会触发ul的事件。

self: 只有点击自身事件才会触发,同时阻止子元素的事件冒泡

    <ul @click.self="onUlClick">
      <li @click="onLiClick">one</li>
      <li @click="onLiClick">two</li>
    </ul>
    // 这样只有点击ul自身的时候才会触发事件,还能阻止li的事件冒泡。

capture:可以将事件处理改为捕获模式,即从外部元素向内部元素传播。

    <ul @click.capture="onUlClick">
      <li>one</li>
      <li>two</li>
    </ul>
    // 这样点击li也会触发事件。

prevent: 阻止默认事件

    <a href='http:xx.com' @click='navigate'></a>
    // 如果我们想在跳转之前做一些处理,这样是无法阻止的。
    
   <a href='http://www.baidu.com' @click.prevent='navigate'>go</a>
   // 这样就能阻止默认行为,触发我们定义的事件去处理逻辑。

js 原生阻止冒泡和默认行为:

w3c是e.stopPropagation()IE则是使用window.event.cancelBubble = true;

w3c是e.prevent()

说到事件冒泡的应用,有一个很好的事情可以说明那就是事件委托;

事件委托也称为事件代理(Event Delegation),事件委托是一种将事件处理程序绑定到一个父元素上,而不是将事件处理程序绑定到每个子元素上的技术。通过事件委托,可以减少事件处理程序的数量,提高性能和代码的可维护性

事件委托正是利用事件流的冒泡特性,将本来要绑定到多个元素的事件函数,委托到了其祖先元素上

//事件代理  节约内存 提升性能(不需要注销子节点)
let ul = document.getElementById("ul");
ul.addEventListener("click", (event) => {
    console.log(event.target.innerHTML);
})