You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// list 的捕获$list.addEventListener('click',(e)=>{console.log('list capturing');e.stopPropagation();},true)// list 捕获 2$list.addEventListener('click',(e)=>{console.log('list capturing2');},true)// list capturing// list capturing2
varitem1=document.getElementById("goSomewhere");varitem2=document.getElementById("doSomething");varitem3=document.getElementById("sayHi");EventUtil.addHandler(item1,"click",function(event){location.href="http://www.wrox.com";});EventUtil.addHandler(item2,"click",function(event){document.title="I changed the document's title";});EventUtil.addHandler(item3,"click",function(event){alert("hi");});
如果在一个复杂的 Web 应用程序中,对所有可单击的元素都采用这种方式,那么结果就会有数不 清的代码用于添加事件处理程序。此时,可以利用事件委托技术解决这个问题。使用事件委托,只需在 DOM 树中尽量最高的层次上添加一个事件处理程序,如下面的例子所示
varlist=document.getElementById("myLinks");EventUtil.addHandler(list,"click",function(event){event=EventUtil.getEvent(event);vartarget=EventUtil.getTarget(event);switch(target.id){case"doSomething":
document.title="I changed the document's title";break;case"goSomewhere":
location.href="http://www.wrox.com";break;case"sayHi": 9alert("hi");break;}}
一、捕获与冒泡
事件流描述的是从页面中接收事件的顺序
IE 的事件流是事件冒泡流
而 Netscape Communicator 的事件流是事件捕获流
DOM2级事件规定的事件流包括三个阶段:
首先发生的是事件捕获,为截获事件提供了机会。
然后是实际的目标接收到事件。
最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应
画重点(这部分内容可以先跳过,看完下面的内容再回头消化)
1、当处于目标阶段,没有捕获与冒泡之分,执行顺序会按照
addEventListener
的添加顺序决定,先添加先执行2、使用
stopPropagation()
取消事件传播时,事件不会被传播给下一个节点,但是,同一节点上的其他listener还是会被执行如果想要同一层级的listener也不执行,可以使用
stopImmediatePropagation()
3、
preventDefault()
只是阻止默认行为,跟JS的事件传播一点关系都没有4、一旦发起了
preventDefault()
,在之后传递下去的事件里面也會有效果二、事件处理程序
共有三种事件处理程序:DOM0、DOM2、IE
画重点:
DOM2级的好处是可以添加多个事件处理程序;DOM0对每个事件只支持一个事件处理程序
通过DOM2添加的匿名函数无法移除,上面写的例子就移除不了,
addEventListener
和removeEventListener
的handler
必须同名作用域:DOM0的
handler
会在所属元素的作用域内运行,IE的handler
会在全局作用域运行,this === window
触发顺序:添加多个事件时,DOM2会按照添加顺序执行,IE会以相反的顺序执行,请谨记
跨浏览器的事件处理程序
三、事件对象
DOM0和DOM2的事件处理程序都会自动传入
event
对象IE中的
event
对象取决于指定的事件处理程序的方法(上面说过)只有在事件处理程序期间,
event
对象才会存在,一旦事件处理程序执行完成,event
对象就会被销毁event对象里需要关心的几个属性
this、currentTarget、target
这三个属性跟冒泡和捕获有关
target
永远是被添加了事件的那个元素,this
和currentTarget
就不一定了(延伸思考:事件处理程序在父节点中的情况)eventPhase
调用事件处理程序的阶段,有三个值
1:捕获阶段
2:处于目标
3:冒泡阶段
阻止默认
preventDefault
与传播stopPropagation
preventDefault:比如链接被点击会导航到其
href
指定的URL
,这个就是默认行为stopPropagation:立即停止事件在DOM层次中的传播,包括捕获和冒泡事件
IE中的对象的对应属性
srcElement
=>target
returnValue
=>preventDefaukt()
cancelBubble
=>stopPropagation()
IE 不支持事件捕获,因而只能取消事件冒泡,但
stopPropagation
可以同时取消事件捕获和冒泡四、跨浏览器的事件对象
根据上面对不同类型的事件以及属性区分
五、事件委托
这一小节在《高程》P403
我自认不能写的比它更精简更好,有些地方就直接搬过来了
事件委托用来解决事件处理程序过多的问题
页面结构如下
按照传统的做法,需要像下面这样为它们添加 3 个事 件处理程序。
如果在一个复杂的 Web 应用程序中,对所有可单击的元素都采用这种方式,那么结果就会有数不 清的代码用于添加事件处理程序。此时,可以利用事件委托技术解决这个问题。使用事件委托,只需在 DOM 树中尽量最高的层次上添加一个事件处理程序,如下面的例子所示
子节点的点击事件会冒泡到父节点,并被这个注册事件处理
最适合采用事件委托技术的事件包括
click
、mousedown
、mouseup
、keydown
、keyup
和keypress
。 虽然mouseover
和mouseout
事件也冒泡,但要适当处理它们并不容易,而且经常需要计算元素的位置。可以考虑为 document 对象添加一个事件处理程序,用以处理页面上发生的某种特定类型的事件,需要跟踪的事件处理程序越少,移除它们就越容易(移除事件处理程序关乎内存和性能)。
只要是通过 onload 事件处理程序添加的东西,最后都要通过 onunload 事件处理程序将它们移除
在事件处理程序中删除按钮也能阻止事件冒泡。目标元素在文档中是事件冒泡的前提。
后记
感谢您耐心看到这里,希望有所收获!
如果不是很忙的话,麻烦右上角点个star⭐,举手之劳,却是对作者莫大的鼓励。
我在学习过程中喜欢做记录,分享的是自己在前端之路上的一些积累和思考,希望能跟大家一起交流与进步,更多文章请看【amandakelake的Github博客】
参考
DOM 的事件傳遞機制:捕獲與冒泡 | TechBridge 技術共筆部落格
What Is Event Bubbling in JavaScript? Event Propagation Explained
The text was updated successfully, but these errors were encountered: