stopPropagation和stopImmediatePropagation

503 阅读1分钟

我们知道js的事件机制存在捕获和冒泡, 一般来说,如果我们只希望事件只触发在目标上,这时候可以使用 stopPropagation 和 stopImmediatePropagation 来阻止事件的进一步传播。

stopPropagation

stopPropagation 的功能是阻止事件传播,包括阻止捕获或冒泡,之前错误的认为只是阻止事件冒泡的。

我们来看一个例子:

  <div id="one">
    <div id="two">
      <div id="three">3</div>
    </div>
  </div>
<style>
div{
  border: 1px solid #111;
  padding: 20px;
}
</style>
<script>
const one = document.querySelector('#one')
const two = document.querySelector('#two')
const three = document.querySelector('#three')

one.addEventListener('click', (e) => {
  console.log('捕获: 1')
}, true)
one.addEventListener('click', (e) => {
  console.log('冒泡: 1')
}, false)

two.addEventListener('click', (e) => {
  console.log('捕获: 2')
  
}, true)

two.addEventListener('click', (e) => {
  console.log('冒泡: 2')
}, false)

three.addEventListener('click', (e) => {
  console.log('捕获: 3')
}, true)

three.addEventListener('click', (e) => {
  console.log('冒泡: 3')
}, false)

</script>

点击3, 打印结果如下,这是完整的捕获和冒泡流程:

捕获: 1
捕获: 2
捕获: 3
冒泡: 3
冒泡: 2
冒泡: 1

我们在2的捕获阶段stopPropagation:

two.addEventListener('click', (e) => {
  e.stopPropagation()
  console.log('捕获: 2')
  
}, true)

点击3, 打印结果如下,事件流在捕获阶段就被阻止了:

捕获: 1
捕获: 2

我们在2的冒泡阶段stopPropagation:

two.addEventListener('click', (e) => {
  e.stopPropagation()
  console.log('冒泡: 2')
}, false)

点击3, 打印结果如下:

捕获: 1
捕获: 2
捕获: 3
冒泡: 3
冒泡: 2

stopImmediatePropagation

stopImmediatePropagation 同样也能实现阻止事件传播, 它与 stopPropagation 的区别是: 还能阻止该监听函数之后注册的监听函数。

我们来看一个例子:

<div>
    <p>paragraph</p>
</div>
<script>
    const p = document.querySelector('p')
    p.addEventListener("click", (event) => {
      alert("我是p元素上被绑定的第一个监听函数");
    }, false);

    p.addEventListener("click", (event) => {
      alert("我是p元素上被绑定的第二个监听函数");
      event.stopImmediatePropagation();
      // 执行stopImmediatePropagation方法,阻止click事件冒泡,并且阻止p元素上绑定的其他click事件的事件监听函数的执行.
    }, false);

    p.addEventListener("click",(event) => {
      alert("我是p元素上被绑定的第三个监听函数");
      // 该监听函数排在上个函数后面,该函数不会被执行
    }, false);

    document.querySelector("div").addEventListener("click", (event) => {
      alert("我是div元素,我是p元素的上层元素");
      // p元素的click事件没有向上冒泡,该函数不会被执行
    }, false);
</script>