javascript 中的事件委托详解

这几天看到一个面试题,大概就是,让你给1000个li都添加一个click事件,应该怎么添加?大多数人第一开始的感觉可能就是,每个li上边都添加一个呗,那要是这样的话,估计面试的时候就会GG了,这里就是撤出了我们的事件冒泡和捕获机制,以及事件委托机制,对于上边这些,我们慢慢来看.

  首先说一下事件冒泡和事件捕获机制,事件冒泡是有微软公司提出来的,事件捕获是有网景公司提出来的,当时两家是争论的不可开交,后来w3c也没办法,就采取了折中的方式,事件产生后先捕获后冒泡,

  通常,在js中监听事件的方法共有三种,分别是:

    ele.addEventListener(type,listener,[useCapture]);//IE6~8不支持

    ele.attachEvent('on'+type,listener);//IE6~10支持,IE11不支持

    ele.onClick=function(){};//所有浏览器都支持

  w3c规范中定义了三个事件阶段,依次是捕获阶段,目标阶段,冒泡阶段,而w3c指定的dom2级规定中,使用的是addEventListener来监听事件的.所以我们就以addEventListener来讲解,首先事假冒泡就像你从往水中扔一块石子,水中的气泡从下边往上冒一样,意思为触发事件后从子元素王父元素方向触发,而捕获机制则正好相反,捕获机制是从父元素往子元素方向进行事件触发,而addEventListener函数中的第三位参数正是来决定是使用捕获机制还是冒泡机制的,当useCapture为true是为捕获机制,当useCapture为false时是冒泡机制,我们看一下例子:

复制代码

<div class="parent">
  <div class="child">

  </div>
</div>
<script>
  var parent = document.getElementsByClassName('parent')[0];
  var child = document.getElementsByClassName('child')[0];

  parent.addEventListener('click',function(){
    console.log("这里是父元素");
  },false);
  child.addEventListener('click',function(){
    console.log("这里是子元素");
  },false);
</script>

  当我们点击子元素是显示上图,当我们将false改为true后就会发现执行顺序会反过来,这就是事件冒泡和捕获的区别,他们两个刚好相反,

  那么使用这种绑定机制我们的弊端在于要去给每一个对象绑定事件会是一个特别麻烦的事情,当我们要删除一个事件或者要改变一个事件的时候会特别的繁琐,更重要的是,我们增加了JavaScript和dom节点之间的关联,而且一点出现循环引用,很有可能造成内存泄露,这些都是它的弊端,

  那么解决这种弊端的一种方法就是事件代理(event delegation),这个方法可以让你避免去给每一个节点一一的添加事件,它的做法是将这些监听事件去绑定到这些节点的父元素上,在父元素上的这个监听函数自动去判断是哪一个子元素触发的事件,从而可以对触发事件的子元素进行操作,这里我们给出的例子是davidwalsh所给出的一个例子:

  现在我们有一个父元素ul和几个li子元素,

<ul id="parent-list">
  <li id="post-1">Item 1</li>
  <li id="post-2">Item 2</li>
  <li id="post-3">Item 3</li>
  <li id="post-4">Item 4</li>
  <li id="post-5">Item 5</li>
  <li id="post-6">Item 6</li>
</ul>

  现在我们要实现的是,当我们点击每一个li节点的时候,都会输出li节点中的内容,按照上边的写法,你可以选中这些li,让后给他们加上这些方法,然后等到不需要了再将他们移除,如果有100个li,1000个li呢,这将会成为你的噩梦,较好的解决方法就是给父元素添加一个监听事件,之后的问题便是怎么去判断出来时哪一个li被点击了? 我们可以在监听事件中去判断当前event的target来判断是否是我们要找的节点,这里我们有一个简单的例子:

// 找到父元素,绑定一个监听事件
document.getElementById("parent-list").addEventListener("click", function(e) {
  // e.target是点击的元素
  // 如果它是li元素
  if(e.target && e.target.nodeName == "LI") {
    //
    console.log("List item ", e.target.id.replace("post-", ""), " was clicked!");
  }
});

  当ul中发生点击事件后,因为addEventListener默认是冒泡事件,所以监听事件会在底层事件冒泡过来时执行,在触发了事件后,去检测是否是我们要寻找的目标元素,如果不是,就会忽略过去,那我们不仅仅可以通过目标元素的标签是不是我们需要的目标元素,我们还可以根据目标元素的属性或者类名来进行检测,利用ele.maeches这个API来进行处理,

document.getElementById("myDiv").addEventListener("click",function(e) {
  // e.target 就是当前被点击的元素
 if (e.target && e.target.matches("a.classA")) {
  console.log("Anchor element clicked!");
  }
});

  因此我们可以看得出来,使用事件代理这种方式,能够给我们带来很多的便捷,可以避免很多坑,使用事件代理是一种很强大的方法.

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

时间: 2016-10-22

老生常谈js动态添加事件--- 事件委托

其所谓的动态添加事件实质就是指js中的事件委托. 我们知道在js中,事件处理只能绑定在当前被选中的元素上,换句话也就是说,事件处理只能绑定在当前文档已经存在的元素上!但是,往往小伙伴们都会遇到一个问题就是,我的元素是后来动态添加到页面的,而我又想给该元素绑定事件,怎么处理? 为了说明白这一问题,我们假设需要给后来添加到当前页面的元素添加click事件. 解决这一问题的核心就是利用js的委托事件.委派事件的优势就是可以给未存在的元素绑定事件,而且委派事件往往开销也会更小! 题外话:举一个最简单的例

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

起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.那这是什么意思呢?网上的各位大牛们讲事件委托基本上都用了同一个例子,就是取快递来解释这个现象,我仔细揣摩了一下,这个例子还真是恰当,我就不去想别的例子来解释了

JavaScript事件委托技术实例分析

本文实例分析了JavaScript事件委托技术.分享给大家供大家参考.具体分析如下: 如果一个整体页面里有大量的按钮.我们就要为每一个按钮绑定事件处理程序.这样就会影响性能了. 首先每个函数都是对象,对象就会占用很多内存.内存中的对象越多,性能就越差. 其次,dom访问次数增多,就会导致延迟加载页面.事实上,从如何来利用好事件处理程序,还是有很好的解决方案的. 事件委托: 对事件处理程序过多的问题解决的方案就是事件委托技术. 事件委托技术利用了事件冒泡.只需指定一个事件处理程序. 我们可以为某个

JavaScript事件委托的技术原理探讨示例

如今的JavaScript技术界里最火热的一项技术应该是'事件委托(event delegation)'了.使用事件委托技术能让你避免对特定的每个节点添加事件监听器:相反,事件监听器是被添加到它们的父元素上.事件监听器会分析从子元素冒泡上来的事件,找到是哪个子元素的事件.基本概念非常简单,但仍有很多人不理解事件委托的工作原理.这里我将要解释事件委托是如何工作的,并提供几个纯JavaScript的基本事件委托的例子. 假定我们有一个UL元素,它有几个子元素: 复制代码 代码如下: <ul id=&qu

JS工作中的小贴士之”闭包“与事件委托的”阻止冒泡“

说下闭包的由来 function a() { var i = 0; function b() { console.log(i); } return b; } var c = a(); c(); 一般来说,当一个函数内部匿名函数用到了自己的变量,并且这个匿名函数被返回了,这就建立了一个闭包,比如上面的代码 这个时候,就算a调用结束被销毁,i也会存在不会消失当a定义时,js解释器会将函数a的作用域链设置为定义a时所在环境当执行a时,a会进入相应的执行环境,执行环境创建后才会有作用域scope属性,然

javascript事件委托的方式绑定详解

js事件绑定 事件绑定,这里使用了冒泡的原理,从点击的元素开始,递归方式的向父元素传播事件,这样做的好处是对于大量要处理的元素,不必为每个元素都绑定事件,只需要在他们的父元素上绑定一次即可,提高性能.还有一个好处就是可以处理动态插入dom中的元素,直接绑定的方式是不行的. 之前一直使用的是jquery的on方法做这样的事情,前几天看到公司项目中有实现这种方式的源代码,拿来仔细研究研究,跟大家分享分享. function $bindAction(dom, event, listeners) { #

javascript性能优化之事件委托实例详解

本文实例分析了javascript性能优化之事件委托.分享给大家供大家参考,具体如下: 为下面每个LI绑定一个click事件 <ul id="myLinks"> <li id="goSomewhere" >Go somewhere</li> <li id="doSomething" >Do something</li> <li id="sayHi" >Sa

javascript事件委托的用法及其好处简析

本文为大家简单介绍了javascript事件委托的用法及其好处,供大家参考,具体内容如下 事件委托:利用冒泡的原理,把事件加到父级上,触发执行效果, 好处:提高性能,新添加的元素还会有之前的事件. event对象:事件源,不管在哪个事件中,只要你操作的那个元素就是事件源 获取事件源: IE:window.event.srcElement 标准下:event.target  target.nodeName来判断是哪个标签 代码应用如下: <!DOCTYPE html PUBLIC "-//W

JavaScript事件委托用法分析

本文实例讲述了JavaScript事件委托用法.分享给大家供大家参考.具体分析如下: 一.点击页面任何部分触发事件 创建一个script1.js文件. 复制代码 代码如下: (function() {     eventUtility.addEvent(document, "click", function(evt) {         alert('hello');     }); }()); 页面部分. 复制代码 代码如下: <head> <meta http-e

JavaScript中的事件委托及好处

1,什么是事件委托:通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件. 也就是:利用冒泡的原理,把事件加到父级上,触发执行效果. 好处呢:1,提高性能. 我们可以看一个例子:需要触发每个li来改变他们的背景颜色. <ul id="ul"> <li>aaaaaaaa</li> <li>bbbbbbbb&l

JavaScript动态添加事件之事件委托

先给大家讲下什么是事件委托:通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件. 也就是:利用冒泡的原理,把事件加到父级上,触发执行效果. 其所谓的动态添加事件实质就是指js中的事件委托. 我们知道在js中,事件处理只能绑定在当前被选中的元素上,换句话也就是说,事件处理只能绑定在当前文档已经存在的元素上!但是,往往小伙伴们都会遇到一个问题就是,我的元素是后来动态

JavaScript事件委托实例分析

本文实例讲述了JavaScript事件委托用法.分享给大家供大家参考.具体如下: var addEvent = function (elem, eventType, func) { if ( elem.addEventListener ) addEvent = function (elem, eventType, func) { elem.addEventListener(eventType, func, false); }; else if ( elem.attachEvent ) addEv

JS 事件绑定、事件监听、事件委托详细介绍

在JavaScript的学习中,我们经常会遇到JavaScript的事件机制,例如,事件绑定.事件监听.事件委托(事件代理)等.这些名词是什么意思呢,有什么作用呢? 事件绑定 要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数.所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称. 在JavaScript中,有三种常用的绑定事件的方法: 在DOM元素中直接绑定: 在JavaScript代码中绑定: 绑定事件监听函数. 在DOM中直接绑定事件

详解使用vue-router进行页面切换时滚动条位置与滚动监听事件

按照正常的产品逻辑,我们在进行页面切换时滚动条应该是在页面顶部的,可是...在使用vue-router进行页面切换时,发现滚动条所处的位置被自动记录了下来,且在另一个组件内定义的滚动监听事件仍会运行,着实吃了一大惊... 说说我的破解方法: 1.在每个需要用vue-router切换的组件的mounted钩子内将页面的位置自动回滚到页面顶部,解决滚动条位置自动记录问题: 2.在每个组件内定义一条变量scrollWatch默认为true,在绑定滚动监听事件时加个if判断,只有在scrollWatch

JS监听事件的叠加和移除功能

html DOM元素有很多on开头的监听事件,如onload.onclick等,见DOM事件列表.但是同一种事件,后面注册的会覆盖前面的: window.onresize = function(){ alert(1); } window.onresize = function(){ alert(2); } // 改变窗口大小时,只会弹出2 addEventListener监听 利用addEventListener添加监听事件,可以重复添加,并不会互相覆盖: window.addEventList

vue v-on监听事件详解

在html或jsp页面中我们总能碰到监听DOM事件来触发javaScript代码,下面我们就简单聊聊Vue.js中的监听事件是怎么处理的. 在vue.js中监听事件是通过v-on指令来实现的,先看一下简单的监听事件代码. <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <scrip

Android开发之Button事件实现与监听方法总结

本文实例总结了Android开发之Button事件实现与监听方法.分享给大家供大家参考,具体如下: 先来介绍Button事件实现的两种方法 main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="

android输入框内容改变的监听事件实例

android输入框内容改变的监听事件一般用于比如我们常见的:登录qq时 用户名输入完整时头像自动显示,或者注册用户时实时提示注册格式是否正确等.那么我们在这里举例:判断输入框是否有内容,来改变按钮的状态,常用于搜索一类.截图如下:(布局代码不再给出) 首先所在的activity要 implements TextWatcher并实现其方法: public void afterTextChanged(Editable arg0) { // 文字改变后出发事件 String content = ed

使用 vue 实例更好的监听事件及vue实例的方法

文章举例说明一下在 vue 中如何更好的监听浏览器事件.原文介绍了一种新增 vue 实例的方法,单独监听事件.这样代码书写较为简练,容易管理. 当监听如下事件的传统做法是: window.scrollX window.scrollY window.innerHeight window.innerWidth 通常需要书写很多代码: created () { this.$el.addEventListener('click', this.someMethod) }, destroyed () { t

layui 数据表格 点击分页按钮 监听事件的实例

找了 很多 关于表格分页 点击事件 请求, table.render 并不支持监听点击事件,所以我就把 table.render 和 laypage.render结合在一起 (我也不想写分页的,但是后台讲数据多 ,要加分页,被逼无奈 ,想了一个方法) 先上图 代码 .html <div> <table class="layui-hide" id="test" lay-filter="demo"></table>

Vue监听事件实现计数点击依次增加的方法

1.实现计数器功能,每点击一次按钮,count值增加一或增加二,鼠标在cordinates行移动时会更新当前坐标,通过自定义函数或者stop属性禁止事件传播. 效果如下: 代码如下: <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>计数器自增函数</title> <script src="vue.js"></s

Android NavigationView头部设置监听事件

NavigationView头部设置监听事件的方法,供大家参考,具体内容如下 1.将XML里的静态引入删除: <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravit