DOM 编程是有交互的,交互就有事件处理程序,一个DOM节点事件还好处理,如果有很多的DOM需要添加事件处理呢?比如我们有100个 li,每个 li 都有相同的 click 点击事件,常规的做法我们可能会用 for 循环的方法,来遍历所有的 li,给每个 li添加事件,这是不是与 都站在门口等快递如出一辙?
事件委托是利用事件的冒泡原理来实现的,何为事件冒泡呢?就是事件从最深的节点开始,然后逐步向上传播事件,举个例子:页面上有这么一个节点树,div>ul>li>a; 比如给最里面的 a 加一个 click 点击事件,那么这个事件就会一层一层的往外执行,执行顺序 a>li>ul>div,有这样一个机制,那么我们给最外面的 div 加点击事件,那么里面的 ul,li,a 做点击事件的时候,都会冒泡到最外层的 div 上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。详情请移步《JavaScript 事件流》
一、概述
1.1、概念
事件委托或者叫事件代理,英文叫
Event Delegation
,JavaScript
高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。通俗点讲,事件委托就是利用事件冒泡原理,把一个或一组元素的事件委托到它的父层或更外层元素上去指定事件处理程序。
概念理解起来还是有点生涩的,前辈们在讲事件委托基本上都用了同一个例子,就是取快递来解释这个现象,认真领会一下是非常有道理的:
有三个同事预计会在周一收到快递。为签收快递,有两种办法:
现实当中,我们大都采用委托的方案,大部分公司也不会容忍那么多员工站在门口就为了等快递。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
结合
DOM
去理解:DOM
节点是有事件的;DOM
节点也是有事件的。1.2、为什么要用事件委托:
DOM
编程是有交互的,交互就有事件处理程序,一个DOM
节点事件还好处理,如果有很多的DOM
需要添加事件处理呢?比如我们有100个li
,每个li
都有相同的click
点击事件,常规的做法我们可能会用for
循环的方法,来遍历所有的li
,给每个li
添加事件,这是不是与都站在门口等快递如出一辙
?在 《浏览器的 reflow 和 repaint》,操作
DOM
会引起浏览器的回流
与重绘
,二者有很大的性能开销,所以要减少DOM
操作。JavaScript
中一切皆对象,对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差了,比如上面的100个li
,就要占用100个内存空间,如果是1000个,10000个呢,那只能说呵呵了,如果用事件委托,那么我们就可以只对它的父级(如果只有一个父级)这一个对象进行操作,这样我们就需要一个内存空间就够了,是不是省了很多,自然性能就会更好。1.3、原理:
事件委托是利用事件的冒泡原理来实现的,何为事件冒泡呢?就是事件从最深的节点开始,然后逐步向上传播事件,举个例子:页面上有这么一个节点树,
div>ul>li>a
; 比如给最里面的a
加一个click
点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div
,有这样一个机制,那么我们给最外面的div
加点击事件,那么里面的ul
,li
,a
做点击事件的时候,都会冒泡到最外层的div
上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。详情请移步《JavaScript 事件流》二、事件委托的实现
假设有下面的代码:
实现功能是点击
li
,控制台中打印li1234
2.1、循环给节点加事件
这段代码通过循环给每个
li
添加鼠标点击事件,其DOM
操作是这样的:先找到ul
节点,遍历该ul
下的li
节点,然后点击li
的时候,再知道目标的li
的位置,执行最后的操作,每次点击都必须找一次li
;2.2、委托给他的父级节点
在《JavaScript 事件流》中,我们知道事件冒泡是从事件发生所在的节点开始,然后逐级传播到
DOM
根节点,是一种自下往上的顺序。因此我们可以在父节点ul
绑定事件。 下面在父节点ul
上绑定事件当
li
被点击时,由于冒泡原理,事件就会冒泡到ul
上,因为ul
上有点击事件,所以事件就会触发,但是这样有个问题:我们并不知道点击的是哪一个具体的li
2.3、Event.target 属性
事件对象
Event
提供了一个target
属性,可以返回触发此事件的目标节点,即事件源,简单点说,target
就可以表示为当前的事件操作的dom
:三、新增节点的事件委托
如下代码,要求鼠标悬停在
li
上,li
背景变为红色。