JS之事件委托
这是属于面试高频问题,今天就来具体说说。
事件委托又名事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。 怎么来理解呢?我们有必要先对事件委托做一个定义。
释义
JS里的事件委托:就是当事件触发时,把要做的事委托给父元素来处理。
再通俗点:就是自己的事不想干,叫它爸爸,甚至爷爷、甚至祖先来干。
举个栗子(菜鸟驿站)。阿甲, 阿乙, 阿丙三个人 预计会在周一收到快递。签收快递有两种办法:一是三个人在公司门口等快递;二是委托给前台代为签收,之后再去领取。现实中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口等快递)。前台收到快递后,会判断收件人是谁,然后按照收件人的要求签收。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台也会在收到寄给新员工的快递后核实并代为签收。
这里其实还隐含有2层意思:
- 在编员工委托前台的同事是可以代为签收的,即程序中的现有的
DOM
节点是有事件的; - 新员工也是可以被前台代为签收的,即程序中新添加的
DOM
节点也是有事件的。
作用和优点
作用1:节约内存
作用2:能为之后新增的DOM元素依然添加事件
优点: 可以大量节省内存占用,减少事件注册
原理
利用事件冒泡原理来实现,只指定一个事件处理程序,管理当前绑定下的所有元素的事件。也就是事件从最内层的节点开始,然后逐步向上传播事件,一层一层的往外执行触发响应,执行顺序由内而外
应用背景
场景1:当多个li标签需要添加点击事件时
传统方式
- 获取
ul
- 通过获取到
ul
去遍历下面的所有li
- 遍历的
li
,依次去注册(绑定)事件
当用事件委托处理时
-
这里用父级
ul
做事件处理,当li
被点击时,由于冒泡原理,事件就会冒泡到ul
上,因为ul
上有点击事件,所以事件就会触发,当然,这里当点击ul
的时候,也是会触发的,那么问题就来了,如果我想让事件代理的效果跟直接给节点的事件效果一样怎么办,比如说只有点击li
才会触发 -
Event对象提供了一个属性叫
target
,可以返回事件的目标节点,我们成为事件源,也就是说,target
就可以表示为当前的事件操作的dom,但是不是真正操作dom,当然,这个是有兼容性的,标准浏览器用e.target
,IE浏览器用event.srcElement。
回顾总结
显而易见得到结论:给所有li
添加点击事件,只要加到它们的父元素ul
身上的根本原因是利用了事件冒泡。也即:无论点击哪个li
,都会自动触发ul
的点击事件,然后在ul
里通过e.target
能获得真正被点击的那个li
,继而拿到它的innerHTML
小结:如果给一堆元素加事件,并且事件触发时执行的代码都差不多时,就可以把事件加在父元素身上啦!这样可以更节省内存空间哦!
看,这样的形式是不是就相当于把自己的事件,委托在父元素身上处理了呢?因而它才会叫事件委托!
也就是:自己的活不干了,给它爹去干!
场景2:新增元素没有绑定事件的问题
界面描述:界面上有一个div
里面默认有2个p
,并且还有一个按钮,当点击按钮就创建一个新的p
,需要不管是默认有的p
还是新的p
都有点击事件。
传统方式
此时会发现:页面刚开始加载时就默认存在的2个p是有点击事件的,但是点击按钮创建出来的p没有点击事件。
原因剖析:因为上面的JS代码是在页面刚加载时执行的,在当时因为不可能去点击按钮,所以能找到的p标签只有默认那2个,因此你打印divps,发现也只有2个
因此,你遍历divps给每个元素加点击事件时,只能给这2个p加到点击事件。因此,如果后面再有p标签,也不拥有点击事件。
使用事件委托解决
可以看到,不管是默认有的2个p还是后面才增加的p都有点击事件了
解析:因为事件冒泡机制的存在,不管是原本有的p
还是新创建的p
,当事件触发时都会一级一级往上调用父元素的同名事件。因此,只要是点击的p
标签,都会触发div
的点击事件,所以只要把事件加在div
身上就解决了不管新旧p
标签都有点击事件的问题。
总结
事件委托的方式,新添加的子元素是带有事件效果的,我们可以发现,当用事件委托的时候,根本就不需要去遍历元素的子节点,整体只注册一次div
事件,并没有给每个p
都注册个监听。这样可以大大的减少dom操作,这就是事件委托
的意义。
下一篇: Java、反射机制和反射的应用
推荐阅读
-
[向过去学习--万花筒] C# 异步编程 逆变委托 事件 事件参数 迭代 线程、多线程、线程池、后台线程
-
向过去学习委托、动作、函数、匿名方法、匿名委托、事件
-
前车之鉴--iOS 事件响应链
-
对用户名、密码、按钮绑定多个事件、网页跳转进行正则表达式判断的 JS 实现
-
Three.js 之 14 Raycaster 灯光投影
-
JS之事件委托
-
AngularJS - 之 - angular-animate.js 使用章节 (ngAnimate)
-
节点监听鼠标和键盘事件、定时消息小程序,解决了机器人js不支持汉字输入的问题!
-
Vue.js:前端开发的灵活之选
-
关于 js 弹出框中的警报事件提示、标题显示页面网址的问题