在JavaScript的事件中,存在事件委托(事件代理),那么什么是事件委托呢?
事件委托在生活中的例子:
有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
事件委托在JavaScript中:
比如要给一个dom节点添加一个点击事件,但是现在事件不加在该dom节点本身,而是加在它的父节点身上,利用它父节点触发事件,给该dom节点实现事件效果。
实现原理:
事件委托是利用事件的冒泡原理来实现的,何为事件冒泡呢?就是事件从最深的节点开始,然后逐步向上传播事件 举个例子:页面上有这么一个节点树,div>ul>li>a
;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div
,有这样一个机制,那么我们给最外面的div加点击事件,让里面的ul,li,a实现事件效果,所以都会触发,这就是事件委托,委托它们父级代为执行事件。
利用事件委托的作用
-
节省资源,提高效率 在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间 如果使用事件委托,则只会与dom节点进行一次交互,有效的减少了和dom交互次数,节省资源,提高效率
-
对于新创建的dom节点,也可以拥有事件
使用场景:
- 重复的给dom节点添加事件
- 给dom树中尚未创建的元素(动态创建)添加事件
使用js添加事件委托
先给出一个例子1:
<ul id="ul"> <li>周一去游玩</li> <li>周二去上班</li> <li>周三去休息</li> <li>周四去吃饭</li> </ul> //利用事件委托给每一个li标签添加点击事件 <script> var ul = document.querySelector("#ul"); ul.onclick = function(){ alert("快醒醒,每天都要上班的!") } </script>
例子中利用父级ul做事件处理,当li被点击时,由于冒泡原理,事件就会冒泡到ul上,因为ul上有点击事件,所以事件就会触发
在例子1中,所有的事件代码都相同,那么如果不同呢? 例子2:
<ul id="ul"> <li>周一去游玩</li> <li class="work-day">周二去上班</li> <li>周三去休息</li> <li>周四去吃饭</li> </ul> <script> var ul = document.querySelector("#ul"); ul.onclick = function(e) { var e = event || window.event; var target = e.srcElement || e.target; if(target.className == "work-day"){ alert("good boy"); }else{ alert("快醒醒,每天都要上班的!"); } } </script>
这个例子中就会针对于class属性等于"word-day"的li元素做出不同的事件,其他事件则为默认事件
jQuery的事件委托
$(function () { $('#ul').on('click', 'li', function () { if ($(this).hasClass('work-day')) { alert("good boy"); } else { alert("快醒醒,每天都要上班的!"); } }) });
总结:
合理使用事件委托可以帮助我们节省资源,提高效率;也可以给dom中尚未创建的节点添加事件(可以自己尝试一下)。
适合用事件委托的事件:
- click
- mousedown
- mouseup
- keydown
- keyup
- keypress
需要小心的是:mouseover和mouseout虽然也有事件冒泡,但是需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易。
不适合用事件委托的事件:
- mousemove(每次都要计算它的位置,非常不好把控)
- focus,blur等(本身就没用冒泡的特性,自然就不能用事件委托了)