什么是事件委托

js中的事件委托或是事件代理详解 

起因:

1、这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的;

2、其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考;

概述:

那什么叫事件委托呢?

它还有一个名字叫事件代理,JavaScript高级程序设计上讲:

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。那这是什么意思呢?网上的各位大牛们讲事件委托基本上都用了同一个例子,就是取快递来解释这个现象,我仔细揣摩了一下,这个例子还真是恰当,我就不去想别的例子来解释了,借花献佛,我摘过来,大家认真领会一下事件委托到底是一个什么原理: 有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。

这里其实还有2层意思的:

第一,现在委托前台的同事是可以代为签收的,即程序中的现有的dom节点是有事件的;

第二,新员工也是可以被前台MM代为签收的,即程序中新添加的dom节点也是有事件的。

为什么要用事件委托:

一般来说,dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了,那如果是很多的dom需要添加事件处理呢?比如我们有100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,然后给它们添加事件,那这么做会存在什么影响呢?

在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;

每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差了(内存不够用,是硬伤,

事件委托的原理:

事件委托是利用事件的冒泡原理来实现的,何为事件冒泡呢?就是事件从最深的节点开始,然后逐步向上传播事件,举个例子:页面上有这么一个节点树,div>ul>li>a;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,那么我们给最外面的div加点击事件,那么里面的ul,li,a做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。

### JavaScript 事件委托的定义、实现及原理解释 #### 一、事件委托的定义 事件委托是一种基于事件冒泡机制的技术,其核心思想是将多个子元素的事件监听器集中绑定到它们共同的父级容器上。这样可以避免为每一个子元素单独绑定事件处理器,从而提升性能简化代码管理[^3]。 #### 二、事件委托的工作原理 事件委托依赖于 **事件冒泡** 的特性。当一个事件发生在某个 DOM 元素上时,该事件会沿着 DOM 树向上传播至祖先节点。因此,即使目标元素本身未注册特定类型的事件监听器,只要它的上级或顶级父节点绑定了相应的监听函数,仍然可以通过捕获这个传播过来的事件来进行响应[^2]。 例如,在下面的例子中,点击任何一个 `<li>` 子项实际上触发的是附加在其父级 `<ul>` 上面的那个单一 click handler: ```javascript document.getElementById('parentList').addEventListener('click', function(event){ if (event.target && event.target.nodeName === 'LI') { console.log(event.target.textContent); // 打印被点击列表项的内容 } }); ``` 这里的关键点在于判断 `event.target` 是否是我们感兴趣的类型 (`<li>`) 执行相应动作[^1]。 #### 三、实现方式 以下是通过事件委托来处理一组按钮点击的具体实例演示: 假设有一个无序列表包含若干链接条目,希望每当用户单击其中任意一项时跳转至对应网址地址。传统做法可能是遍历所有 `<a>` 标签逐一挂载 onclick 方法;但借助事件委派模式,则只需要在包裹这些锚点标签的父亲层面上设立统一侦听即可完成相同效果。 ```html <ul id="linkContainer"> <li><a href="#sectionA">Section A</a></li> <li><a href="#sectionB">Section B</a></li> <li><a href="#sectionC">Section C</a></li> </ul> <script type="text/javascript"> const container = document.querySelector('#linkContainer'); container.addEventListener('click', function(e) { const linkElm = e.target.closest('a'); if (!linkElm || !linkElm.matches('a')) return; e.preventDefault(); history.pushState({}, '', linkElm.getAttribute('href')); updateContentBasedOnHash(); // 自定义方法更新页面内容 }, false); </script> ``` 此段脚本首先选取了作为所有超链载体的 ul 容器对象,接着为其添加了一个通用型鼠标按键按下回调闭包。每当检测到来自内部组件发出的通知信号之后,便会进一步确认发送源确实属于预期范围之内(即有效的 a 标记),随后阻止默认行为发生以便自行控制导航流程[^4]。 #### 四、优势总结 - 减少了全局范围内创建过多独立事件句柄所带来的开销; - 动态增删后代节点不影响已存在的监听逻辑有效性; - 维护起来更加方便直观易于扩展升级[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值