惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Hugging Face - Blog
Hugging Face - Blog
IT之家
IT之家
Jina AI
Jina AI
Google DeepMind News
Google DeepMind News
大猫的无限游戏
大猫的无限游戏
The GitHub Blog
The GitHub Blog
腾讯CDC
L
LangChain Blog
P
Proofpoint News Feed
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
量子位
Apple Machine Learning Research
Apple Machine Learning Research
Cloudbric
Cloudbric
B
Blog RSS Feed
B
Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Vercel News
Vercel News
S
Schneier on Security
Project Zero
Project Zero
宝玉的分享
宝玉的分享
美团技术团队
MyScale Blog
MyScale Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Spread Privacy
Spread Privacy
T
Threatpost
A
Arctic Wolf
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hacker News - Newest:
Hacker News - Newest: "LLM"
爱范儿
爱范儿
Recorded Future
Recorded Future
C
CERT Recently Published Vulnerability Notes
T
Threat Research - Cisco Blogs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
SecWiki News
SecWiki News
H
Hacker News: Front Page
AWS News Blog
AWS News Blog
博客园_首页
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tor Project blog
C
Check Point Blog
L
Lohrmann on Cybersecurity
F
Full Disclosure
TaoSecurity Blog
TaoSecurity Blog
Google Online Security Blog
Google Online Security Blog
云风的 BLOG
云风的 BLOG
The Last Watchdog
The Last Watchdog
Martin Fowler
Martin Fowler

mafeifan 的编程技术分享

mafengwo-mp3-downloader | mafeifan 的编程技术分享 示例页面 | mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 查看 default namespace 下的 default service account名称 mafeifan 的编程技术分享 检查日志 | mafeifan 的编程技术分享 bridge fdb show dev flannel.1 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 数据收集原理分析 | mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 几种方法 | mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 check the export on the very top of this document so we can use $do mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 mafeifan 的编程技术分享 运维自动化之ANSIBLE | mafeifan 的编程技术分享 延伸 -- 关于前端路由 xdebug 3 和 2 的区别
mafeifan 的编程技术分享
2026-01-16 · via mafeifan 的编程技术分享

冒泡与捕获的由来 ​

我们知道HTML中的元素是可以嵌套的,形成类似于树的层次关系。比如下面的代码:

html

<div id="outA" style="height:300px;width:300px;padding:50px;background:gray;">A  
    <div id="outB" style="height:200;width:200px;padding:50px;background:blue;"> B 
		<div id="outC" style="height:100px;width:100px;background:yellow;">C</div>   
    </div> 
</div>

然后效果如下:

如果点击了最里面的outC,那么外层的outB和outC算不算被点击了呢?很显然算,不然就没有必要区分事件冒泡和事件捕获了,这一点各个浏览器厂家也没有什么疑义。假如outA、outB、outC都注册了click类型事件处理函数,当点击outC的时候,触发顺序是A-->B-->C,还是C-->B-->A呢?

如果浏览器采用的是事件冒泡,那么触发顺序是C-->B-->A,由内而外,像气泡一样,从水底浮向水面;如果采用的是事件捕获,那么触发顺序是A-->B-->C,从上到下,像石头一样,从水面落入水底。

一般来说事件冒泡机制,用的更多一些,所以在IE8以及之前,IE只支持事件冒泡。IE9+/FF/Chrome这2种模型都支持,可以通过addEventListener((type, listener, useCapture)的useCapture来设定,useCapture=false代表着事件冒泡,useCapture=true代表着采用事件捕获。

DOM事件流 ​

假如我们在outC元素上同时绑定了冒泡和捕获两种阶段的事件

javascript

  window.onload = function(){     
    var outC = document.getElementById("outC");    
      
    // 目标(自身触发事件,是冒泡还是捕获无所谓)  
    outC.addEventListener('click',function(){alert("target1");},false);  
    outC.addEventListener('click',function(){alert("target2");},true);        
  };

是冒泡先执行还是会捕获先执行呢。答案:对于自身触发事件,是冒泡还是捕获无所谓。先注册的先执行,后注册的后执行。

另外要理解DOM事件流,DOM事件流:将事件分为三个阶段:捕获阶段、目标阶段、冒泡阶段。先调用捕获阶段的处理函数,其次调用目标阶段的处理函数,最后调用冒泡阶段的处理函数。

更近一步,给三个div都绑定冒泡和捕获事件。想想,如果分别点击ABC三个div,执行顺序是什么呢?

javascript

  window.onload = function(){  
      var outA = document.getElementById("outA");    
      var outB = document.getElementById("outB");    
      var outC = document.getElementById("outC");    
        
      // 目标(自身触发事件,是冒泡还是捕获无所谓)  
      outC.addEventListener('click',function(){alert("target2");},true);  
      outC.addEventListener('click',function(){alert("target1");},false);  
        
      // 事件冒泡  
      outA.addEventListener('click',function(){alert("bubble1");},false);  
      outB.addEventListener('click',function(){alert("bubble2");},false);  
        
      // 事件捕获  
      outA.addEventListener('click',function(){alert("capture1");},true);  
      outB.addEventListener('click',function(){alert("capture2");},true); 
  };

点击C

分析:

  • 捕获阶段:从最外层到元素C,先执行各个元素上的点击事件capture1->capture2
  • 目标阶段:C上绑定了两个单击事件,按绑定顺序依次执行target2->target1
  • 冒泡阶段:从内到外bubble2->bubble1

最终的执行顺序: capture1->capture2->target2->target1->bubble2->bubble1

点击B,执行顺序: capture1->bubble2->capture2->bubble1 点击A,执行顺序: bubble1->capture1

阻止事件冒泡和捕获 ​

默认情况下,多个事件处理函数会按照DOM事件流模型中的顺序执行。如果子元素上发生某个事件,不需要执行父元素上注册的事件处理函数,那么我们可以停止捕获和冒泡,避免没有意义的函数调用。 IE8以及以前可以通过 window.event.cancelBubble=true阻止事件的继续传播;IE9+/FF/Chrome通过event.stopPropagation()阻止事件的继续传播。

修改代码

javascript

  // 目标  
  outC.addEventListener('click',function(event){  
      alert("target");  
      event.stopPropagation();  
  },false);  

  // 事件冒泡  
  outA.addEventListener('click',function(){alert("bubble");},false);  

  // 事件捕获  
  outA.addEventListener('click',function(){alert("capture");},true);

当点击outC的时候,只会打印出capture->target,不会打印出bubble。因为当事件传播到outC上的处理函数时,通过stopPropagation阻止了事件的继续传播,所以不会继续传播到冒泡阶段。

继续修改代码

javascript

	// 目标  
	outC.addEventListener('click',function(event){ alert("target");}, false);  

	// 事件冒泡  
	outA.addEventListener('click',function(){ alert("bubble");}, false);  

	// 事件捕获  
	outA.addEventListener('click',function(event){ 
		alert("capture"); 
		event.stopPropagation();
	}, true);

当点击outC的时候,只会打印出capture而没有触发outC上的事件处理函数。 因为outA上的捕获事件是先执行的,触发了里面event.stopPropagation()就不会再执行任何传播事件了。

引申 ​

preventDefault, stopPropagation, stopImmediatePropagation和return false的区别

preventDefault, stopPropagation, stopImmediatePropagation都是event提供的方法

event.stopPropagation

event.stopPropagation阻止捕获和冒泡阶段中当前事件的进一步传播。

event.preventDefault

如果事件可取消,则取消该事件,而不停止事件的进一步传播。 它可以阻止事件触发后默认动作的发生。

可用来阻止input框非法内容的输入,checkbox被选中等

WARNING

注意:preventDefault 方法不会阻止该事件的进一步冒泡。stopPropagation 方法才有这样的功能.

event.stopImmediatePropagation

这个方法会做两件事情:

Keeps the rest of the handlers from being executed and prevents the event from bubbling up the DOM tree.

第一件事:阻止绑定在事件触发元素的其他同类事件的运行,看下面的例子就很明白:

javascript

$("p").click(function(event) {
  event.stopImmediatePropagation();
});
$("p").click(function(event) {
  // 不会执行以下代码
  $(this).css("background-color", "#f00");
});

第二件事,阻止事件传播到父元素,这跟stopPropagation的作用是一样的。

stopImmediatePropagation比stopPropagation多做了第一件事情,这就是他们之间的区别。

WARNING

注意:不要用return false;来阻止event的默认行为,原因请见

关于 addEventListener 和 on ​

使用on后面的会覆盖前面事件,而addEventListener不会 比如页面上有 <div id="box">追梦子</div>

javascript

window.onload = function(){
  var box = document.getElementById("box");
  box.onclick = function(){
    console.log("我是box1");
  }
  box.onclick = function(){
    box.style.fontSize = "18px";
    console.log("我是box2");
  }
}

运行结果:"我是box2"

javascript

window.onload = function(){
  var box = document.getElementById("box");
  box.addEventListener("click",function(){
    console.log("我是box1");
  })
  box.addEventListener("click",function(){
    console.log("我是box2");
  })
}

运行结果:我是box1, 我是box2

关于addEventListener的第三个参数,true代表捕获阶段处理, false代表冒泡阶段处理。不写默认false。

参考 ​