事件委托
所谓事件委托就是利用事件冒泡,指定事件的某一处理程序就可以管理某一类型的所有事件
有一个经典的例子来解释事件委托原理:
有三个同事预计在同一天会收到快递,有两种取快递的办法,一种是三个同事同时下楼在门口等快递,另一种是委托给前台人员,帮忙代领快递,自己来取的时候只需要报自己的姓名既可,即使公司来了新同事,前台人员也会对快递进行核实然后帮其代领。
这段例子中包含两层含义:
第一:委托给前台人员的快递是可以代收的,即dom节点是有事件的
第二:新同事的快递也可以被前台人员代收,即新添加的dom节点也是有事件的
使用事件委托的目的
如果我们有100个li,每个li都有点击事件,用for循环给每个li添加事件会影响页面的整个性能,这是因为需要不断的dom节点进行交互,当节点的访问次数增加时,引起浏览器的重绘和重排的次数增加,就会延长浏览器的就绪和交互时间
事件委托的原理
事件委托是由事件冒泡实现的,就是从底层节点开始,逐级向上传播。例如在一个无序列表ul中嵌套多个li,并且每个li都有个超链接,点击li,事件的执行顺序为a>li>ul,事件都会冒泡到最外层ul,给最外层设置事件,即委托给父级代其执行事件
事件委托的实现
下面我们来看一个简单的例子
html
<ul id='list'>
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
</ul>
每次点击li都会弹出hello world
javascript
window.onload = function(){
var list = document.getElementById("list");
var li = list.getElementByTagName("li");
for(var i = 0; i<li.length; i++){
li[i].onclick = function(){
alert("hello world");
}
}
}
上述的例子非常简单,利用for循环给每个li添加点击事件,如果用事件委托该怎么处理呢?
javascript
window.onload = function(){
var list = document.getElementById("list");
list.onclick = function(){
alert("hello world");
}
}
这里用ul做事件处理,当li被点击时,会冒泡到ul上,由于ul有点击事件,所以会被触发。
如果我们想让事件代理的效果和直接给节点加事件的效果一样怎么办?
Event对象提供了解决方案,该对象提供了target属性可以返回事件的目标节点,也就意味着target就是当前目标节点。但这里又存在着兼容性问题,标准浏览器使用event.target,ie使用event.srcElement,下面来看改进之后的效果
window.onload = function(){ var list = document.getElementById("list");
list.onclick = function(event){
var event = event||window.event;
var target = event.target|| event.srcElement;
if (target.nodeName.toLowerCase=="li"){
alert("hello world");
}
}
}
如果每个组件添加的事件不一样,该怎么办呢?
看下面例子
<div id="btn-group">
<input type="button" id="add" value="添加">
<input type="button" id="delete" value="删除">
<input type="button" id="update" value="修改">
<input type="button" id="query" value="查询">
</div>
window.onload = function () {
var box = document.getElementById("btn-group");
box.onclick = function (event) {
var event = event||window.event;
var target = event.target||event.srcElement;
if (target.nodeName.toLowerCase()==="input"){
switch (target.id){
case 'add':
alert("添加");
break;
case 'delete':
alert("删除");
break;
case 'update':
alert("修改");
break;
case 'query':
alert("查询");
break;
}
}
}
}
这样就可以实现利用事件委托添加不同的事件了。