欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

JS之事件委托

最编程 2024-04-12 20:15:08
...

这是属于面试高频问题,今天就来具体说说。

事件委托又名事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。 怎么来理解呢?我们有必要先对事件委托做一个定义。

释义

JS里的事件委托:就是当事件触发时,把要做的事委托给父元素来处理。

再通俗点:就是自己的事不想干,叫它爸爸,甚至爷爷、甚至祖先来干。

举个栗子(菜鸟驿站)。阿甲, 阿乙, 阿丙三个人 预计会在周一收到快递。签收快递有两种办法:一是三个人在公司门口等快递;二是委托给前台代为签收,之后再去领取。现实中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口等快递)。前台收到快递后,会判断收件人是谁,然后按照收件人的要求签收。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台也会在收到寄给新员工的快递后核实并代为签收。

这里其实还隐含有2层意思:

  1. 在编员工委托前台的同事是可以代为签收的,即程序中的现有的DOM节点是有事件的;
  2. 新员工也是可以被前台代为签收的,即程序中新添加的DOM节点也是有事件的。

作用和优点

作用1:节约内存

作用2:能为之后新增的DOM元素依然添加事件

优点: 可以大量节省内存占用,减少事件注册

原理

利用事件冒泡原理来实现,只指定一个事件处理程序,管理当前绑定下的所有元素的事件。也就是事件从最内层的节点开始,然后逐步向上传播事件,一层一层的往外执行触发响应,执行顺序由内而外

应用背景

场景1:当多个li标签需要添加点击事件时

1656147709584.png

传统方式
  1. 获取ul
  2. 通过获取到ul去遍历下面的所有li
  3. 遍历的li,依次去注册(绑定)事件

1656149053260.jpg

1656149094224.jpg

当用事件委托处理时
  • 这里用父级ul做事件处理,当li被点击时,由于冒泡原理,事件就会冒泡到ul上,因为ul上有点击事件,所以事件就会触发,当然,这里当点击ul的时候,也是会触发的,那么问题就来了,如果我想让事件代理的效果跟直接给节点的事件效果一样怎么办,比如说只有点击li才会触发

  • Event对象提供了一个属性叫target,可以返回事件的目标节点,我们成为事件源,也就是说,target就可以表示为当前的事件操作的dom,但是不是真正操作dom,当然,这个是有兼容性的,标准浏览器用e.target,IE浏览器用event.srcElement。

1656149392207.jpg

1656149411424.jpg

回顾总结

显而易见得到结论:给所有li添加点击事件,只要加到它们的父元素ul身上的根本原因是利用了事件冒泡。也即:无论点击哪个li,都会自动触发ul的点击事件,然后在ul里通过e.target能获得真正被点击的那个li,继而拿到它的innerHTML

小结:如果给一堆元素加事件,并且事件触发时执行的代码都差不多时,就可以把事件加在父元素身上啦!这样可以更节省内存空间哦!

看,这样的形式是不是就相当于把自己的事件,委托在父元素身上处理了呢?因而它才会叫事件委托!

也就是:自己的活不干了,给它爹去干!

场景2:新增元素没有绑定事件的问题

界面描述:界面上有一个div里面默认有2个p,并且还有一个按钮,当点击按钮就创建一个新的p,需要不管是默认有的p还是新的p都有点击事件。

传统方式

1656150598535.jpg

此时会发现:页面刚开始加载时就默认存在的2个p是有点击事件的,但是点击按钮创建出来的p没有点击事件。

原因剖析:因为上面的JS代码是在页面刚加载时执行的,在当时因为不可能去点击按钮,所以能找到的p标签只有默认那2个,因此你打印divps,发现也只有2个

因此,你遍历divps给每个元素加点击事件时,只能给这2个p加到点击事件。因此,如果后面再有p标签,也不拥有点击事件。

使用事件委托解决

1656151027298.jpg

1656151003406.jpg

可以看到,不管是默认有的2个p还是后面才增加的p都有点击事件了

解析:因为事件冒泡机制的存在,不管是原本有的p还是新创建的p,当事件触发时都会一级一级往上调用父元素的同名事件。因此,只要是点击的p标签,都会触发div的点击事件,所以只要把事件加在div身上就解决了不管新旧p标签都有点击事件的问题。

总结

事件委托的方式,新添加的子元素是带有事件效果的,我们可以发现,当用事件委托的时候,根本就不需要去遍历元素的子节点,整体只注册一次div事件,并没有给每个p都注册个监听。这样可以大大的减少dom操作,这就是事件委托的意义。