详解JS事件冒泡、事件捕获原型 stopPropagation()和preventDefault()作用

一、两种事件流的由来

要解释由来,先要解释一下为什么会产生事件流。

当浏览器发展到第四代时,浏览器开发团队发现一个问题,当你单击一个按钮的时候,你也单击了按钮的容器元素,还单击了整个页面。这就有意思了,当你给按钮和按钮的容器元素都添加了点击事件,那么是哪个的点击事件先执行呢?

针对这个问题,就产生了事件流——描述的是页面中接收事件的顺序。但是当时的不同的开发团队提出了两种完全相反的事件流,IE提出的事件流是:事件冒泡流,而Netscape Communicator提出的事件流是:事件捕获流

二、事件冒泡和事件捕获的区别

1、事件冒泡:事件开始由最具体的元素接收,然后逐级向上传播到较不具体的节点(document)
2、事件捕获:事件开始由不太具体的节点接收,然后逐级向下传播到最具体的节点

W3C把这两种事件流整合在了一起变成了DOM事件流,DOM事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,然后是目标接收到事件,最后一个阶段是冒泡阶段。
DOM事件流的原型

  • 在支持W3C标准的浏览器上,就可以使用addEventListener()方法来指定在什么阶段调用事件处理程序。使用方法为: element.addEventListener(event, funciton, userCapture)
    可以通过设置userCapture的值来选择使用什么事件流,值为false时,事件是在事件冒泡时执行;值为true时,事件在事件捕获时执行。默认为false。

  • 但在不支持W3C标准的浏览器上,如IE可以使用 attachEvent(event, function)方法,IE的事件模型默认是在事件冒泡时执行的,不能设置为事件捕获流。

所以把addEventListener()的userCapture设置为false是比较安全的,也实现了浏览器的兼容。
JS事件捕获和事件冒泡原型图
总结下来就是:

  1. 事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)
  2. 事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签

假设有一个div元素中有一个子元素p

<div id="parent">
	<p id="child">这是文本</p>
</div>

当两个元素都绑定了点击事件,如果用户点击了p,它在div和p上都触发了click事件,那这两个事件处理程序哪个先执行呢?事件顺序是什么?
在冒泡阶段调用事件处理程序时

document.getElementById("parent").addEventListener("click",function(e){
                alert("parent元素被点击");
            },false);
document.getElementById("child").addEventListener("click",function(e){
                alert("child元素被点击");
            },false);

结果:

child元素被点击
parent元素被点击

结论:当你使用事件冒泡时,子级元素先触发,父级元素后触发,即p先触发,div后触发。

在事件捕获阶段调用事件处理程序时:

document.getElementById("parent").addEventListener("click",function(e){
                alert("parent元素被点击");
            },true);
document.getElementById("child").addEventListener("click",function(e){
                alert("child元素被点击");
            },true);

结果:

parent元素被点击
child元素被点击

结论:当你使用事件捕获时,父级元素先触发,子级元素后触发,即div先触发,p后触发。

ps:使用传统绑定事件方式也是采用的事件冒泡方式。
如 element.οnclick=function(){}

三、stopPropagation()和preventDefault()作用

有时候我们需要阻止事件的向上冒泡
  • 在支持W3C标准下:使用event.stopPropagation()
  • 在IE下:设置cancelBubble = true
有时候我们需要取消事件的默认行为
  • 在支持W3C标准下:使用event.preventDefault()
  • 在IE下:设置window.event.returnValue = false
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值