JavaScript网页开发中经常出现的就是事件处理程序,交互越多可能就需要注册更多的事件处理程序,这也导致了一定的性能问题:
- 事件处理函数是对象,对象存储于内存空间,对象越多消耗的内存也就越大
- 事件注册需要在页面交互就绪前访问DOM元素,注册的DOM越多,访问时间越长
解决这个问题的一种方法就是事件委托。事件委托是依赖于事件冒泡机制(IE事件流,从最具体的元素开始接收事件,逐级向上传递直至最顶层文档),我们先来看一个利用事件冒泡为element元素注册一个点击处理程序:
//DOM2 第三个参数为false表示冒泡机制 element.addEventListener("click", function(){ /* ... */ }, false); //IE element.attachEvent("onclick", function(){ /* ... */ });
事件委托是一个什么概念呢?
其实就是在父级元素上注册事件处理程序(依据事件的具体接收元素执行相应的代码片段),用来替代在多个子孙元素上的事件注册。
举一个偏极端的例子,比如原本页面中有许多DOM元素都绑定了点击事件,现在进行事件委托,只在最顶层的文档(document)注册一个点击处理程序,通过点击事件的target属性可以获得点击具体的接收元素,根据元素的tagName、ID等进行不同的处理就可以实现事件委托。
document.addEventListener("click", function(event){ //IE的attachEvent函数中是event.srcElement var target = event.target; switch(target.id){ /* ... */ } }, false);
当然我们应该去实现更加合理的事件委托。
比如一个UL-LI标签栏,点击不同的LI标签则展现对应的内容,如果给每个LI标签都注册一个点击事件会造成一定的性能浪费。我们就可以只在该UL元素上注册一个点击事件通过LI的属性值来区分具体的接收元素,然后就可以进行该LI标签处理程序片段。
<ul class="nav">
<li id="bbcode">BBCode编辑器</li>
<li id="visual">可视化编辑器</li>
<li id="preview">预览</li>
</ul>
PS:动态生成的元素也适用于事件委托。