事件冒泡和事件捕获与事件委托和事件代理
大概在毕业前实习的那段日子,在了解了jQuery的delegate方法后,想去知其然和所以然。于是学习了事件冒泡,因为没有加以运用,时至今却对其一知半解了。不靠理解的学习方式等于无数无意义的重复。所以在再次学习事件冒泡这个东西的时候,我想先用自己的思维方式大刀阔斧一番。
1.事件冒泡,事件捕获,事件委托,事件代理都是什么?
名不正则言不顺,首先对以上四个常见的名词加以解释。作为一个非处女座典型强迫症主义患者,实在不能忍受委托和代理有什么不同。通过各种搜索引擎发现,事件委托和事件代理同样来自与Event delegate这个单词——只是含义不同!我们知道,宿主环境(大多数情况下是浏览器)给HTML元素绑定了各种各样的事件用以相应用户操作,正因如此,不同的浏览器甚至不同的操作系统都会具有自己特点的一面,针对这些不同会引发一系列兼容性问题。在事件冒泡中,与之对应的事件捕获也是兼容性的一种体现。到现在为止,我们可以得出下表:
兼容性 | 同语义 |
---|---|
事件捕获 | 事件代理 |
事件冒泡 | 事件委托 |
2. 冒泡和代理之间的关系
在DOM中,存在一个文档树的概念,即任何页面都有一个根节点。一般的,这个节点为<html></html>
。在这个节点下,有很多种父子关系,兄弟关系等构成页面。常见的比如
<div class="col-xs-12">
<a class="btn btn-default" href="javascript:void(0);">Link</a>
</div>
或者
<div class="click">
<input type="submit" value="submit" />
</div>
一般的,我们会针对<a>
和<input>
绑定事件,然而当我们需要在父类上添加一些漂亮的表现效果时。在这里由于事件的传递(冒泡和捕获)方式影响了父类,就是说当我们给父类绑定了事件,即便单击了子类元素,事件会层层传递一直到达根节点(或者当前节点)。显然这不是我们所希望的,尤其是当DOM结构会动态变化时,比如表格中的CRUD操作时。如果使用了传统的处理方式,非现代浏览器(不会自动更新的浏览器)会有很大的内存开销。这个时候,我们可以利用事件传递的特性,使用代理的方法来解决这个问题。只需要在所有节点共同的父类上绑定相同的事件,然后判断目标来源,即可得到用户相应的当前元素。
为什么会有冒泡这种特性存在呢?我查询了一些资料:What is event bubbling and capturing?这个答案虽然在解释冒泡和捕获的不同。但是却启发了我理解冒泡的来源:盒模型。假设我们的文档树是用一个个盒子来表现关系,那么当我们想要给里面的盒子注册事件时,必然需要将外层盒子一个个打开,这个过程就发生了事件传递。当我用盒子假设来理解这个现象时,关于事件代理和阻止冒泡也就不难想象了。
3.学以致用
当我们习惯了使用传统方式添加各种事件的时候,一方面容易停滞不前,另一方面给维护也带来不少麻烦。如果是交互性比较强的页面,甚至会看到满屏的Element.onclick = function (){}
。利用事件代理,只需要注册(addEventListener || attachEvent)一个click方法,然后使用Event.target
区别不同的元素。这样做的好处在结构化代码增强易读性时,会越来越有帮助。
几个问题:
- 注册事件的方法有哪几种?
- addEventListener 和 attachEvent有何不同?
function (e){e.target}
中的e代表什么?e.target
有无兼容性问题?
2015.04.05夜 小雨 公寓