DOM事件对象(addEventListener())
2017-01-03 14:45
134 查看
DOM2事件模型
DOM2事件模型相对于DOM0,小菜仅仅了解如下两点:
· DOM2支持同一dom元素注册多个同种事件。
· DOM2新增了捕获和冒泡的概念。
DOM2事件通过addEventListener和removeEventListener管理,当然,这是标准。
但IE8及其以下版本浏览器,自娱自乐,搞出了对应的attachEvent和detachEvent,由于小菜才疏学浅,本文不做讨论。
addEventListener当然就是注册事件,她有三个参数,分别为:"事件名称", "事件回调", "捕获/冒泡"。举个例子:
事件名称就不用多说了,相比DOM0,去掉了前边的on而已。
事件回调也很好理解,事件触发了总得通知你吧!回调时和DOM0一样,也会默认传入一个event参数,同时this是指触发该事件的dom节点。
最后一个参数是布尔型,true代表捕获事件,false代表冒泡事件。其实很好理解,先来个示意图:
意思就是说,某个元素触发了某个事件,最先得到通知的是window,然后是document,依次而入,直到真正触发事件的那个元素(目标元素)为止,这个过程就是捕获。接下来,事件会从目标元素开始起泡,再依次而出,直到window对象为止,这个过程就是冒泡。
为什么要这样设计呢?这貌似是由于深厚的历史渊源,小菜也不怎么了解,就不乱说了。
由此可以看出,捕获事件要比冒泡事件先触发。
假设有这样的html结构:
然后我们在外层div上注册两个click事件,分别是捕获事件和冒泡事件,代码如下:
最后,点击内层的div,先弹出ok1,后弹出ok。结合上边的原理图,外层div相当于图中的body,内层div相当于图中最下边的div,证明了捕获事件先执行,然后执行冒泡事件。
为什么要强调点击内层的div呢?因为真正触发事件的dom元素,必须是内层的,外层dom元素才有机会模拟捕获事件和冒泡事件,从原理图上就看出了。
如果在真正触发事件的dom元素上注册捕获事件和冒泡事件呢?
html结构同上,js代码如下:
当然还是点击内层div,结果是先弹出ok,再弹出ok1。理论上应该先触发捕获事件,也就是先弹出ok1,但是这里比较特殊,因为我们是在真正触发事件的dom元素上注册的事件,相当于在图中的div上注册,由图可以看出真正触发事件的dom元素,是捕获事件的终点,是冒泡事件的起点,所以这里就不区分事件了,哪个先注册,就先执行哪个。本例中,冒泡事件先注册,所以先执行。
这个道理适用于多个同种事件,比如说一下子注册了3个冒泡事件,那么执行顺序就按照注册的顺序来,先注册先执行。例如:
结果当然是依次弹出ok、ok1、ok2。
为了进一步理解事件模型,还有一种场景,假如说外层div和内层div同时注册了捕获事件,那么点击内层div时,外层div的事件一定是先触发的,代码如下:
结果是先弹出ok1。
假如外层div和内层div都是注册的冒泡事件,点击内层div时,一定是内层div事件先执行,原理相同。
细心的读者会发现,对于div嵌套的情况,如果点击内层的div,外层的div也会触发事件,这貌似会有问题!
点击的明明是内层div,但是外层div的事件也触发了,这的确是个问题。
其实,事件触发时,会默认传入一个event对象,前边提过了,这个event对象上有一个方法:stopPropagation,通过此方法,可以阻止冒泡,这样外层div就接收不到事件了。代码如下:
终于要说说怎么解除事件了。解除事件语法:btn.removeEventListener("事件名称", "事件回调", "捕获/冒泡");
这和绑定事件的参数一样,详细说明下:
· 事件名称,就是说解除哪个事件呗。
· 事件回调,是一个函数,这个函数必须和注册事件的函数是同一个。
· 事件类型,布尔值,这个必须和注册事件时的类型一致。
也就是说,名称、回调、类型,三者共同决定解除哪个事件,缺一不可。举个例子:
要想注册过的事件能够被解除,必须将回调函数保存起来,否则无法解除。
DOM2事件模型相对于DOM0,小菜仅仅了解如下两点:
· DOM2支持同一dom元素注册多个同种事件。
· DOM2新增了捕获和冒泡的概念。
DOM2事件通过addEventListener和removeEventListener管理,当然,这是标准。
但IE8及其以下版本浏览器,自娱自乐,搞出了对应的attachEvent和detachEvent,由于小菜才疏学浅,本文不做讨论。
addEventListener当然就是注册事件,她有三个参数,分别为:"事件名称", "事件回调", "捕获/冒泡"。举个例子:
1 var btn = document.getElementById("test"); 2 3 btn.addEventListener("click", function(e){ 4 alert("ok"); 5 }, false);
事件名称就不用多说了,相比DOM0,去掉了前边的on而已。
事件回调也很好理解,事件触发了总得通知你吧!回调时和DOM0一样,也会默认传入一个event参数,同时this是指触发该事件的dom节点。
最后一个参数是布尔型,true代表捕获事件,false代表冒泡事件。其实很好理解,先来个示意图:
意思就是说,某个元素触发了某个事件,最先得到通知的是window,然后是document,依次而入,直到真正触发事件的那个元素(目标元素)为止,这个过程就是捕获。接下来,事件会从目标元素开始起泡,再依次而出,直到window对象为止,这个过程就是冒泡。
为什么要这样设计呢?这貌似是由于深厚的历史渊源,小菜也不怎么了解,就不乱说了。
由此可以看出,捕获事件要比冒泡事件先触发。
假设有这样的html结构:
1 <div id="test" class="test">2 <div id="testInner" class="test-inner"></div>3 </div>
然后我们在外层div上注册两个click事件,分别是捕获事件和冒泡事件,代码如下:
1 var btn = document.getElementById("test"); 2 3 //捕获事件 4 btn.addEventListener("click", function(e){ 5 alert("ok1"); 6 }, true); 7 8 //冒泡事件 9 btn.addEventListener("click", function(e){ 10 alert("ok"); 11 }, false);
最后,点击内层的div,先弹出ok1,后弹出ok。结合上边的原理图,外层div相当于图中的body,内层div相当于图中最下边的div,证明了捕获事件先执行,然后执行冒泡事件。
为什么要强调点击内层的div呢?因为真正触发事件的dom元素,必须是内层的,外层dom元素才有机会模拟捕获事件和冒泡事件,从原理图上就看出了。
如果在真正触发事件的dom元素上注册捕获事件和冒泡事件呢?
html结构同上,js代码如下:
1 var btnInner = document.getElementById("testInner"); 2 3 //冒泡事件 4 btnInner.addEventListener("click", function(e){ 5 alert("ok"); 6 }, false); 7 8 //捕获事件 9 btnInner.addEventListener("click", function(e){ 10 alert("ok1"); 11 }, true);
当然还是点击内层div,结果是先弹出ok,再弹出ok1。理论上应该先触发捕获事件,也就是先弹出ok1,但是这里比较特殊,因为我们是在真正触发事件的dom元素上注册的事件,相当于在图中的div上注册,由图可以看出真正触发事件的dom元素,是捕获事件的终点,是冒泡事件的起点,所以这里就不区分事件了,哪个先注册,就先执行哪个。本例中,冒泡事件先注册,所以先执行。
这个道理适用于多个同种事件,比如说一下子注册了3个冒泡事件,那么执行顺序就按照注册的顺序来,先注册先执行。例如:
1 var btnInner = document.getElementById("testInner"); 2 3 btnInner.addEventListener("click", function(e){ 4 alert("ok"); 5 }, false); 6 7 btnInner.addEventListener("click", function(e){ 8 alert("ok1"); 9 }, false); 10 11 btnInner.addEventListener("click", function(e){ 12 alert("ok2"); 13 }, false);
结果当然是依次弹出ok、ok1、ok2。
为了进一步理解事件模型,还有一种场景,假如说外层div和内层div同时注册了捕获事件,那么点击内层div时,外层div的事件一定是先触发的,代码如下:
1 var btn = document.getElementById("test"); 2 var btnInner = document.getElementById("testInner"); 3 4 btnInner.addEventListener("click", function(e){ 5 alert("ok"); 6 }, true); 7 8 btn.addEventListener("click", function(e){ 9 alert("ok1"); 10 }, true);
结果是先弹出ok1。
假如外层div和内层div都是注册的冒泡事件,点击内层div时,一定是内层div事件先执行,原理相同。
细心的读者会发现,对于div嵌套的情况,如果点击内层的div,外层的div也会触发事件,这貌似会有问题!
点击的明明是内层div,但是外层div的事件也触发了,这的确是个问题。
其实,事件触发时,会默认传入一个event对象,前边提过了,这个event对象上有一个方法:stopPropagation,通过此方法,可以阻止冒泡,这样外层div就接收不到事件了。代码如下:
1 var btn = document.getElementById("test"); 2 var btnInner = document.getElementById("testInner"); 3 4 btn.addEventListener("click", function(e){ 5 alert("ok1"); 6 }, false); 7 8 btnInner.addEventListener("click", function(e){ 9 //阻止冒泡10 e.stopPropagation(); 11 alert("ok"); 12 }, false);
终于要说说怎么解除事件了。解除事件语法:btn.removeEventListener("事件名称", "事件回调", "捕获/冒泡");
这和绑定事件的参数一样,详细说明下:
· 事件名称,就是说解除哪个事件呗。
· 事件回调,是一个函数,这个函数必须和注册事件的函数是同一个。
· 事件类型,布尔值,这个必须和注册事件时的类型一致。
也就是说,名称、回调、类型,三者共同决定解除哪个事件,缺一不可。举个例子:
1 var btn = document.getElementById("test"); 2 //将回调存储在变量中 3 var fn = function(e){ 4 alert("ok"); 5 }; 6 //绑定 7 btn.addEventListener("click", fn, false); 8 9 //解除10 btn.removeEventListener("click", fn, false);
要想注册过的事件能够被解除,必须将回调函数保存起来,否则无法解除。
相关文章推荐
- JS冒泡事件与事件捕获实例详解
- jQuery中阻止冒泡事件的方法介绍
- Js冒泡事件详解及阻止示例
- jquery的冒泡事件的阻止与允许(三种实现方法)
- 关于IE浏览器以及Firefox下的javascript冒泡事件的响应层级
- JS冒泡事件的快速解决方法
- JS阻止冒泡事件以及默认事件发生的简单方法
- js阻止默认事件与js阻止事件冒泡示例分享 js阻止冒泡事件
- js捕获鼠标滚轮事件代码
- Jquery之事件冒泡和移出事件
- WPF冒泡事件
- js阻止冒泡事件小案例
- js:浏览器的默认行为怎么消除
- 阻止冒泡事件发生
- js之事件冒泡和事件捕获详细介绍
- js事件探秘
- 事件模型--冒泡与捕获
- JS阻止冒泡
- js事件委托原理
- [微信小程序]微信小程序点击事件返回值的target分析