(冒泡和捕获)子元素和父元素之间相互的默认传递及其阻断的方法

一、概述:

  冒泡和捕获并不难理解,正如标题所言,他们指子元素和父元素之间的,两个方法的效果截然相反。

捕获指的是父元素默认向子元素传递事件(事件自上向下的传递);

冒泡指的是子元素默认向父元素传递事件(事件自下向上的传递);

二、详细解释:

冒泡

冒泡的原理是当一个事件发生在一个元素上,它会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序。

举个例子:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>mphbh</title>
</head>
<body>
    <style>
        body * {
    margin: 10px;
    border: 1px solid blue;
  }
    </style>
    
<form οnclick="alert('form')">FROM
    <div οnclick="alert('div')">DIV
     <p οnclick="alert('p')">P</p>
    </div>
</form>
</body>
</html>

在上述代码运行的网页中点击内部的 <p> 会依次运行不同的 onclick事件

  1. 在该 <p> 上的。
  2. 然后是外部 <div> 上的。
  3. 然后是外部 <form> 上的。
  4. 以此类推,直到最后的 document 对象。

因此,如果我们点击 <p>,那么我们将看到网页上会依次出现 3 个 alert:p → div → form,这个过程称之为“冒泡”。

注意:

1.几乎所有事件都会冒泡,并不绝对,比如fouces事件不会冒泡等等

2.我们通常称引发事件那个嵌套层级最深的元素(即最底层元素)为目标元素,可以通过event.target 进行访问(如上例中的<p>)

停止冒泡

冒泡事件从目标元素开始向上冒泡。通常,它会一直上升到 <html>,然后再到 document 对象,有些事件甚至会到达 window,它们会调用路径上所有的处理程序。

但是任意处理程序都可以决定事件已经被完全处理,并停止冒泡

用于停止冒泡的方法是 event.stopPropagation()

举个简单的例子:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>

<body οnclick="alert(event will spread there)">
    <button οnclick="event.stopPropagation">click me</button>
</body>
</html>

这里<body>中的onclick事件不会工作,这就实现了冒泡的阻断

注意:

1.如果一个元素一个事件上有多个处理程序,即使其中一个停止冒泡,其他处理程序仍会执行。

换句话说:event.stopPropagation() 停止向上移动,但是当前元素上其他处理程序都会继续运行。

2.event.stopImmediatePropagation() 方法,不仅可以用于停止冒泡,也阻止了当前元素上的处理程序运行。使用该方法之后,其他处理程序就不会被执行

3.不要在没有需要的情况下停止冒泡!

捕获

捕获的原理是当我们点击目标元素时,会先从最外层元素的事件逐步向下逐步运行,直到进入到目标元素为止。

DOM事件标准描述了事件传播的 3 个阶段:

  1. 捕获阶段(Capturing phase)—— 事件(从 Window)向下走近元素。
  2. 目标阶段(Target phase)—— 事件到达目标元素。
  3. 冒泡阶段(Bubbling phase)—— 事件从元素上开始冒泡。

如图所示:

捕获的默认状态是关闭的,在运行程序时,捕获阶段很少被使用。所有通常我们看不到它。

使用 on<event> 属性或使用 HTML 特性(attribute)使用两个参数的 addEventListener(event, handler) 添加的处理程序,对捕获一无所知,它们仅在第二阶段和第三阶段运行。

为了在捕获阶段捕获事件,我们需要将处理程序的 capture 选项设置为 true:

elem.addEventListener(...,{capture:true})// 或者,用 {capture: true} 的别名 "true"elem.addEventListener(...,true)

capture 选项有两个可能的值:

  • 如果为 false(默认值),则在冒泡阶段设置处理程序。
  • 如果为 true,则在捕获阶段设置处理程序。

如上述冒泡例子(我们略作修改:激活冒泡):

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>mphbh</title>
</head>
<body>
    <style>
        body * {
    margin: 10px;
    border: 1px solid blue;
  }
    </style>
    
<form >FROM
    <div >DIV
     <p >P</p>
    </div>
</form>
    <script>
  for(let elem of document.querySelectorAll('*')) {
    elem.addEventListener("click", e => alert(`Capturing: ${elem.tagName}`), true);
    elem.addEventListener("click", e => alert(`Bubbling: ${elem.tagName}`));
  }
</script>
</body>
</html>

激活捕获之后,如果你继续点击<p>,那么事件发生的顺序是:

  1. HTML → BODY → FORM → DIV(捕获阶段,第一个监听器)
  2. P(目标阶段,触发两次,因为我们设置了两个监听器:捕获和冒泡)
  3. DIV → FORM → BODY → HTML(冒泡阶段,第二个监听器)

注意:

1.激活捕获后,要移除处理程序,addEventListener 和removeEventListener需要一一对应,即

addEventListener(. . . , true)和 removeEventListener(. . . , true)要一一对应

2.同一元素的同一阶段的监听器按其设置顺序运行

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现元素元素的点击事件同时生效,您可以使用事件冒泡和事件捕获机制来处理。 事件冒泡是指事件从最具体的元素开始触发,然后逐级向上冒泡元素,直至根元素。而事件捕获则是相反的过程,事件从根元素开始触发,然后逐级向下捕获至最具体的元素默认情况下,事件会按照事件冒泡方式进行处理。因此,当您在元素上触发点击事件时,该事件将首先在元素上触发,然后冒泡元素,最后到达根元素。 您可以通过在元素上添加事件处理程序来同时处理元素元素的点击事件。以下是一个示例: HTML: ```html <div id="parent"> <div id="child"></div> </div> ``` JavaScript: ```javascript document.getElementById('parent').addEventListener('click', function () { console.log('元素被点击'); }); document.getElementById('child').addEventListener('click', function (event) { event.stopPropagation(); // 阻止事件冒泡 console.log('元素被点击'); }); ``` 在上述代码中,我们分别给元素元素添加了点击事件处理程序。在元素的点击事件处理程序中,我们使用了 `event.stopPropagation()` 方法来阻止事件冒泡,从而避免元素触发相同的点击事件。 这样一来,当您在元素上点击时,元素的点击事件会被触发,并阻止事件冒泡元素。同时,元素的点击事件也会触发。 希望以上信息对您有所帮助!如果您有任何其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值