浏览器中的事件捕获和冒泡

js是一门事件驱动的编程语言,事件通常有多种,比如说网络事件,IO事件,定时事件,点击事件等等。 在这里先只关注下前端浏览器中的事件。

什么事件

如同字面意思,事件就代表了一件事或一个动作,浏览器中的事件有哪些

window事件form事件keyboard事件mouse事件media事件
afterprintonbluronkeydownonclickonabort
beforeprintonchangeonkeypressondbclickoncanplay
onloadoncontextmenuonkeyupondragoncanplaythrough
onunloadonformchangeongragendondurationchange
onbeforeunloadonforminputondragenteronemptied
onerroronforcusondragleaveonended
onhaschangeoninputondragoveronerror
onmessageoninvalidondragstartonloadeddata
onofflineonresetondroponloadedmetadata
ononlineonselectonmousedownonloadstart
onpagehideonsubmitonmousemoveonpause
onpageshowonmouseoutonplay
onpopstateonmouseoveronplaying
onredoonmouseoveronprogress
onresizeonmoseuponratechange
onstorageonmosewhellonreadystatechange
onundoonscrollonseeked
onunloadonseeking
onstalled
onsuspend
ontimeupdate
onvolumechange
onwaiting

事件触发过程

从上面各方各面的事件上我们可以看出浏览器冲加载到退出那一刻,无时不刻不在触发事件,那么事件触发是怎样的一个流程呢?

输入图片说明

当dom节点发生了某些操作时,就会有一个事件发射出去,这个事件从window发出,不断经过下级节点知道目标节点,这个阶段称为捕获阶段。所有经过的节点都会触发这个事件,捕获阶段的任务就是建立事件传递线路,以便后面冒泡阶段顺着该线路返回至window。监听该阶段的事件,可以通过把addEventListener第三个参数设为true

node.addEventListener('click', function() {}, true);

当事件传递到目标节点哪里,最终会在目标节点上触发这个事件,这个就是目标阶段(事件触发的目标总是最最底层的节点:如<p>hello <em>world</em></p>,目标节点可以是p也可以是em)

当事件到达目标节点之后,会沿捕获阶段的路线原路返回,这个阶段称为冒泡阶段,同样沿途所有的节点都会再次触发该事件。

监听父节点

由事件的触发机制我们可以看到,沿途所有的父节点都会被触发两次该事件,一次是捕获阶段,一次是冒泡阶段。

node.addEventListener('click', functioon() {console.log('hello')}, true) ; //捕获阶段
node.addEventListener('click', function() {console.log('world')}, false); //冒泡阶段

所以我们可以通过冒泡机制来监听父节点的事件,实现监听子节点,尤其是当子节点非常多的时候

注:由于IE浏览器不支持在捕获阶段监听事件,所有通常只用冒泡阶段来监听事件。

冒泡的烦恼

事件的冒泡机制,虽然很好,但有些场合并不使用。在比较复杂的应用中,监听比较复杂,我们可能只希望监听发生具体事件的节点,这个时候就要阻止冒泡

阻止冒泡可以使用事件对象的stopPropagation方法

node.addEventListener('click', function(e) {
    //operations
    e.stopPropagation();    
}, false);

事件对象

在阻止冒泡时我们使用到了事件对象,那么事件对象是什么? 当一个事件被触发的时候,会创建一个事件对象,这里面包含了一些有用的属性和方法,事件对象会作为回调函数的的第一个参数(如同node回调第一个参数永远是error一样)

<body>
  <div class="one">
    <div class="two">
      <div class="three">

      </div>
    </div>
  </div>
</body>

node.addEventListener('click', function(e) {
    console.log('事件对象', e)
}, false);

事件对象的属性和方法等(方法大部分上是对属性的get方法)

属性描述方法描述
altKeyaddEventListener添加事件绑定
bubbles是否在冒泡阶段触发removeEventListener删除事件绑定
buttonstopPropagation停止冒泡
buttonspreventDefault禁止浏览器默认行为
cancelBubbledispatchEvent手动触发事件(var event=new Event('click'); element.dispatchEvent(event)
cancelable是否可以调用proventDefault来禁止
clientX
clientY
composed
ctrlKey
currentTarget
defaultPrevented是否禁止了默认行为
detail
eventPhase当前事件触发在什么阶段。none:0;捕获:1;目标:2;冒泡:3
fromElement
isTrusted浏览器触发(用户真实操作触发),还是 JavaScript 代码触发的
layerX
layerY
metaKey
movementX
movementY
offsetX
offsetY
pageX页面的坐标
pageY页面的坐标
path事件路径
relatedTarget
returnValue
screenX
screenY
shiftKey
sourceCapabilities
srcElementie6-8 的触发事件的 dom 元素,非标准
target触发的目标节点
timeStamp返回事件发生时的时间戳
toElement
type事件类型
view
which
x
y

事件代理

传统的事件绑定存在两个不足的地方:1)需要绑定很多个eventhandler 2)事件无法绑定后加入的节点。 事件的代理或委托就是事件触发过程中冒泡机制和事件对象的应用,j简单的结构如下

document.getElementById("parent-list").addEventListener("click",function(e) {
	// e.target是被点击的元素!
	// 如果被点击的是li元素
	if(e.target && e.target.nodeName == "li") {
		// 找到目标,输出ID!
		console.log("find");
	}
});

转载于:https://my.oschina.net/u/1249401/blog/805445

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值