一、写在前头

   接到某厂电话问什么是事件代理的时候,一开始说addEventListener,然后他说直接绑定新的元素不会报dom不存在的错误吗?然后我就混乱了,我印象中这个方法是可以绑定新节点的。后面才知道,原来他要考察的是事件委托(代理)的原理,他指的是未来还不清楚会创建多少个节点,所以没办法实现给他们注册事件。

二、事件委托(事件代理)的作用?

为了方便理解,我先把事件委托的作用写一下。

  1. 支持为同一个DOM元素注册多个同类型事件
  2. 可将事件分成事件捕获和事件冒泡机制

例子解析:

  • 注册多个事件

用以往注册事件的方法,如果存在多个事件,后注册的事件会覆盖先注册的事件

//index.html
<div id="div1"></div> window.onload = function(){
let div1 = document.getElementById('div1');
div1.onclick = function(){
console.log('打印第一次')
}
div1.onclick = function(){
console.log('打印第二次')
}
}

可以看到第二个点击注册事件覆盖了第一个注册事件,只执行了console.log('打印第二次');

用addEventListener(type,listener,useCapture)实现

  • type: 必须,String类型,事件类型
  • listener: 必须,函数体或者JS方法
  • useCapture: 可选,boolean类型。指定事件是否发生在捕获阶段。默认为false,事件发生在冒泡阶段
<div id="div1"></div>

window.onload = function(){
let div1 = document.getElementById('div1');
div1.addEventListener('click',function(){
console.log('打印第一次')
})
div1.addEventListener('click',function(){
console.log('打印第二次')
})
}

可以看到两个注册事件都成功触发了。 useCapture是事件委托的关键,我们后面详解

  • 事件捕获和事件冒泡机制
  1. 事件捕获

    当一个事件触发后,从Window对象触发,不断经过下级节点,直到目标节点。在事件到达目标节点之前的过程就是捕获阶段。所有经过的节点,都会触发对应的事件
  2. 事件冒泡

    当事件到达目标节点后,会沿着捕获阶段的路线原路返回。同样,所有经过的节点,都会触发对应的事件

通过例子理解两个事件机制:

例子:假设有body和body节点下的div1均有绑定了一个注册事件.

效果:

    当为事件捕获(useCapture:true)时,先执行body的事件,再执行div的事件

    当为事件冒泡(useCapture:false)时,先执行div的事件,再执行body的事件

//当useCapture为默认false时,为事件冒泡
<body>
<div id="div1"></div>
</body> window.onload = function(){
let body = document.querySelector('body');
let div1 = document.getElementById('div1');
body.addEventListener('click',function(){
console.log('打印body')
})
div1.addEventListener('click',function(){
console.log('打印div1')
})
} //结果:打印div1 打印body

//当useCapture为true时,为事件捕获
<body>
<div id="div1"></div>
</body> window.onload = function(){
let body = document.querySelector('body');
let div1 = document.getElementById('div1');
body.addEventListener('click',function(){
console.log('打印body')
},true)
div1.addEventListener('click',function(){
console.log('打印div1')
})
} //结果:打印body 打印div1

三、事件委托和新增节点绑定事件的关系?

事件委托的优点:

  1. 提高性能:每一个函数都会占用内存空间,只需添加一个事件处理程序代理所有事件,所占用的内存空间更少。
  2. 动态监听:使用事件委托可以自动绑定动态添加的元素,即新增的节点不需要主动添加也可以一样具有和其他元素一样的事件。

    例子解析:
<script>
window.onload = function(){
let div = document.getElementById('div'); div.addEventListener('click',function(e){
console.log(e.target)
}) let div3 = document.createElement('div');
div3.setAttribute('class','div3')
div3.innerHTML = 'div3';
div.appendChild(div3)
}
</script> <body>
<div id="div">
<div class="div1">div1</div>
<div class="div2">div2</div>
</div>
</body>

虽然没有给div1和div2添加点击事件,但是无论是点击div1还是div2,都会打印当前节点。因为其父级绑定了点击事件,点击div1后冒泡上去的时候,执行父级的事件。

分别点击div1、div2、div3



这样无论后代新增了多少个节点,一样具有这个点击事件的功能。这一个就是考察者想要听到的答案。

彻底弄懂JS事件委托的概念和作用的更多相关文章

  1. js进阶 12-2 彻底弄懂JS的事件冒泡和事件捕获

    js进阶 12-2 彻底弄懂JS的事件冒泡和事件捕获 一.总结 一句话总结:他们是描述事件触发时序问题的术语.事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件.相反的,事件 ...

  2. JS事件委托的原理和应用

    js事件委托也叫事件代理,实际上事件委托就是通过事件冒泡实现的,所谓的事件就是onclick,onmouseover,ondown等等,那么委托呢?委托就是指本来这个事是要你自己做的,但是你却让别人帮 ...

  3. JS事件委托学习(转)

    JS 事件委托就是利用冒泡原理,把事件加到父级上触发,执行效果. 好处: 1.提高性能 2.新添加的元素还会有之前的事件     <</</</</li></ ...

  4. js事件委托 jQuery写法

    http://www.cnblogs.com/liugang-vip/p/5616484.html 不是抄的,这篇文章写的细 这是js 事件委托写法 <!DOCTYPE html> < ...

  5. 原生js事件委托(事件代理)方法扩展

    原生js事件委托(事件代理)方法扩展: 通过Node底层原型扩展委托方法 /** * 事件委托方法 * @param eventName {string}:事件名称,如'click' * @param ...

  6. 彻底弄懂JS的事件冒泡和事件捕获(不推荐阅读)

    由于搬去敌台了,好久没来博客园,今天无意中翻到有“误认子弟”的评论,这里特意做个说明. 本文中关于事件冒泡和事件捕获的描述和例子都是OK的,错就错在后面用jquery去展示了利用事件冒泡的例子有误,其 ...

  7. 彻底弄懂JS的事件冒泡和事件捕获

      先上结论:在事件执行流中有两种执行方式.一种是事件冒泡(即事件的执行顺序是从下往上执行的) ;  另一种是捕获(即事件的执行顺序是从上往下执行的); 阻止事件冒泡:   return false; ...

  8. JavaScript中的this详解(彻底弄懂js中的this用法)!

    要想学好js,那么其中那些特别令人混淆迷惑的知识点,就一定要弄清楚.this关键字就是其中让初学者比较迷惑的知识点之一,不过灵活运用this可以提升代码的性能和复用性,那么今天我就和大家一起来了解th ...

  9. js事件委托或事件代理

    起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...

随机推荐

  1. js如何获取服务器端时间?

    用js做时间校正,获取本机时间,是存在bug的. 使用js也可获取到服务器时间,原理是使用 ajax请求,返回的头部信息就含有服务器端的时间信息,获取到就可以了.以下: 1.依赖jQuery 代码: ...

  2. es6基本语法

    //let和const申明变量和常量 //作用域只限于当前代码块 //使用let申明的变量作用域不会提升 //在相同的作用域下不能申明相同的变量 //for循环体现let的父子作用域 二.es6的解构 ...

  3. GUI常用对话框5

    %输入对话框 name = inputdlg('请输入姓名','实例'); ret = inputdlg({'请输入姓名','请输入性别'},'实例') %一个输入表中多行输入 %留言对话框 info ...

  4. html5的理解

    1.良好的移动性,以移动设备为主 2.响应式设计,以适应自动变化的屏幕尺寸 3.支持离线缓存技术,webStorage本地缓存 4.新增canvas.video.audio等新标签元素,新增特殊内容元 ...

  5. Java 安全套接字编程以及keytool 使用最佳实践

    概述 利用 Java 的 JSSE(Java Secure Socket Extension)技术,我们可以方便的编写安全套接字程序,关于 JSSE 的介绍,可以参阅 Oracle 网站提供的 JSS ...

  6. c++ STL中的next_permutation

    default (1) template <class BidirectionalIterator> bool next_permutation (BidirectionalIterato ...

  7. php 获取最近一周,一个月,一年

    <?php date_default_timezone_set('PRC'); /** * 获取最近一周,一个月,一年 * */ function getLatelyTime($type = ' ...

  8. P3203 [HNOI2010]弹飞绵羊(LCT)

    P3203 [HNOI2010]弹飞绵羊 LCT板子 用一个$p[i]$数组维护每个点指向的下个点. 每次修改时cut*1+link*1就解决了 被弹出界时新设一个点,权为0,作为终点表示出界点.其他 ...

  9. DDos攻击的常见方法及防御方法

    什么是DDoS? DDoS是英文Distributed Denial of Service的缩写,意即“分布式拒绝服务”,那么什么又是拒绝服务(Denial of Service)呢?可以这么理解,凡 ...

  10. 锁(lock)和闩(latch)

    开发多用户.数据库驱动的应用时,最大的难点之一是:一方面要力争取得最大限度的并发访问,与此同时还要确保每个用户能以一致的方式读取和修改数据.为此就有了锁定(locking)机制,这也是所有数据库都具有 ...