事件委托

为什么要用事件委托???事件委托有什么好处???

一般来说,dom是需要有事件处理程序的,我们会直接给他事件处理程序就好了,那么如果是很多dom元素需要添加事件处理呢???
比如 100个li,每个li 都有相同的click点击事件,可能我们会有for循环的方法,来遍历所有li,然后为每个li添加绑定事件。
这么做毫无疑问的是对性能有很大的影响;

在js中,添加到页面上的事件处理程序的多少将直接关系到页面运行的整体性能,因为需要不断的与dom节点进行交互,访问dom次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间。
这就是性能优化,减少dom操作的原因;

如果采用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只交互一次,这样减少了dom交互次数,性能就会提升;
事件委托原理:
事件委托就是利用事件冒泡原理实现的!
事件冒泡:就是事件从最深节点开始,然后逐步向上传播事件;
例:页面上有一个节点树,div > ul  > li  >  a
比如给最里面的a 加一个click 事件,那么事件就会一层一层的往外执行,执行顺序 a > li > ul > div,  有这样一个机制,当我们给最外层的div 添加点击事件,那么里面的ul , li  , a  做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托他们父集代为执行事件;

业务需求:实现功能,点击td ,单元格变色;
html结构
[html]  view plain  copy
  1. <!-- 事件绑定 -->  
  2.     <table id="myTable" border="1">  
  3.         <tr>  
  4.             <td>1</td>  
  5.             <td>2</td>  
  6.             <td>3</td>  
  7.         </tr>  
  8.     </table>  
[javascript]  view plain  copy
  1. window.onload = function(){  
  2.     var oTa = document.getElementById("myTable");  
  3.     var aTd = oTa.getElementsByTagName('td');  
  4.     for(var i=0;i<aTd.length;i++){  
  5.         aTd[i].onclick = function(){  
  6.             aTd[i].style.background = 'red';  
  7.         }  
  8.     }  
  9. }  
上面的办法是最简单的办法,也是最笨的办法,我们看看执行了多少次dom操作,首先找到table 然后遍历td ,当点击td的时候,又要找一次目标的li的位置,才能执行最后的操作,每次点击都要找一次td

那我们用 事件委托的方式怎么来写呢,??

[javascript]  view plain  copy
  1. window.onload = function(){  
  2.     var oTa= document.getElementById("myTable");  
  3.     oTa.onclick = function(){         //点击 table、td均可以alert(123)  
  4.        alert(123);    
  5.     }}  
[javascript]  view plain  copy
  1. <pre></pre>  
  2. <pre></pre>  
这里用父集做事件处理,当td被点击时,由于冒泡原理事件就会冒泡到table上,因此table上有点击事件,所以事件就会被触发;
当然单当点击table本身的时候也是会触发的;
如果我们只想让td触发而不想让table触发,怎么办呢???

Event对象提供了一个属性叫做 target,可以返回事件的目标节点,我们称之为事件源,也就是说,target就可以表示 当前事件操作的dom,但可能不是真正操作的dom,
存在兼容性问题:标准浏览器:event.target,IE浏览器:event.srcElement,
此时只是获取了当前节点的位置,但并不知道节点名称,这里我们用 nodeName来获取具体是什么标签名,这个返回值是一个大写的,判断时需要转换为小写;
[javascript]  view plain  copy
  1. window.onload = function(){  
  2.   var oTa = document.getElementById("myTable");  
  3.   oTa.onclick = function(e){  
  4.     var e = e || window.event;                    //处理兼容性  
  5.     var target = e.target || e.srcElement;     
  6.     target.nodeName.toLowerCase() == 'td' ? alert('我点中了table') :(target.style.background = 'red');  //三元运算符进行判断  
  7.   }  
  8. }  
这样改一下,就只有td会触发事件啦,且每次只执行一次dom操作,如果td很多的话,将大大减小dom的操作;
上面的例子是说td点击都是产生同样的效果,要是每个td被点击的效果都不一样,那么事件委托还有用吗,???
[javascript]  view plain  copy
  1. <!-- 事件绑定 -->  
  2.     <table id="myTable" border="1">  
  3.         <tr>  
  4.             <td id="add">增加</td>  
  5.             <td id="delete">删除</td>  
  6.             <td id="modfiy">修改</td>  
  7.             <td id="select">查找</td>  
  8.         </tr>  
  9.     </table>  
非事件委托写法
[javascript]  view plain  copy
  1. window.onload = function(){  
  2.             var Add = document.getElementById("add");  
  3.             var Delete = document.getElementById("delete");  
  4.             var Move = document.getElementById("move");  
  5.             var Select = document.getElementById("select");  
  6.               
  7.             Add.onclick = function(){  
  8.                 alert('添加');  
  9.             };  
  10.             Remove.onclick = function(){  
  11.                 alert('删除');  
  12.             };  
  13.             Move.onclick = function(){  
  14.                 alert('移动');  
  15.             };  
  16.             Select.onclick = function(){  
  17.                 alert('选择');  
  18.             }  
  19.               
  20.         }  
4个按钮,点击每一个做不同的动作,,,那么至少需要4次dom操作;
如果用事件委托,能进行优化吗?
事件委托写法
[javascript]  view plain  copy
  1. window.onload = function(){  
  2.             var myTable = document.getElementById("myTable");  
  3.             myTable.onclick = function (ev) {     
  4.                 var ev = ev || window.event;  
  5.                 var target = ev.target || ev.srcElement;  
  6.                 if(target.nodeName.toLocaleLowerCase() == 'table'){  
  7.                     switch(target.id){  
  8.                         case 'add' :  
  9.                             alert('添加');  
  10.                             break;  
  11.                         case 'remove' :  
  12.                             alert('删除');  
  13.                             break;  
  14.                         case 'move' :  
  15.                             alert('移动');  
  16.                             break;  
  17.                         case 'select' :  
  18.                             alert('选择');  
  19.                             break;  
  20.                     }  
  21.                 }  
  22.             }  
  23.               
  24.         }  
用事件委托,只用一次dom操作,就能完成所有的效果,性能肯定比上面的好;

前面讲的都是document 加载完成后现有的dom节点的操作;
那么如果是新增的节点,新增的节点会有事件吗???也就是说,新来的一个员工,他能收到快递吗????
看一下正常添加节点的方法:
[javascript]  view plain  copy
  1. <input type="button" name="" id="btn" value="添加" />  
  2.     <ul id="ul1">  
  3.         <li>111</li>  
  4.         <li>222</li>  
  5.         <li>333</li>  
  6.         <li>444</li>  
  7.     </ul>  
用一般的方法,循环加给li加点击事件,你会发现新增的li 没有事件!!!
解决办法:
一般情况下,我们会用一个函数把那个for循环包起来,然后再在点击事件里调用这个函数,这样也能实现目的,功能虽然实现了,但无疑又增加了dom操作,
事件委托的方式如何做呢???
[javascript]  view plain  copy
  1. <script type="text/javascript">  
  2.     window.onload = function(){  
  3.         var ul1 = document.getElementById('ul1');  
  4.         var li = document.getElementsByTagName('li');  
  5.         var btn = document.getElementById('btn');  
  6.         var num = 1;  
  7.         // for(var i=0;i<li.length;i++){  
  8.         //  li[i].onclick = function(){  
  9.         //      alert(this.innerHTML);  
  10.         //  }  
  11.         //  num++;  
  12.         // }  
  13.         ul1.onclick = function(e){  
  14.             var e = e || window.event;  
  15.             var target = e.target || event.srcElement;  
  16.             console.log(target.nodeName);  
  17.             target.nodeName.toLowerCase() == 'li' ? alert(target.innerHTML) : alert("您点中了ul标签");  
  18.         }  
  19.   
  20.         btn.onclick = function(){  
  21.             var oLi = document.createElement('li');  
  22.             oLi.innerHTML = 111*num;  
  23.             ul1.appendChild(oLi);  
  24.         }  
  25.     }  
上面是用事件委托的方式, 新添加的子元素也是有点击功能的;
我们可以发现,当用事件委托的时候,根本不需要遍历元素的子节点,只需要给父级元素添加事件就好了,
其他的代码都是在js里面执行的,这样可以大大减少dom操作,
这就是我理解的事件委托的精髓;

jQuery事件委托:
我直接上code了,jquery的操作是如此的简单,一个on全搞定!!!
[html]  view plain  copy
  1. <!-- 事件绑定 -->  
  2.     <table id="myTable" border="1">  
  3.         <tr>  
  4.             <td>111</td>  
  5.             <td>222</td>  
  6.             <td>333</td>  
  7.             <td>444</td>  
  8.         </tr>  
  9.     </table>  
[javascript]  view plain  copy
  1. <script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>  
  2. <script type="text/javascript">  
  3.     $(function(){         
  4.         $("#myTable td").click(function(){    
  5.             $(this).html();  //普通写法,如果有100个td元素,就要绑定100次事件,十分浪费性能  
  6.         })  
  7.           
  8.   
  9.           
  10.         $("#myTable").click(function(e){    //这种点击方式怎么排除父元素????  
  11.             console.log(e.target);  
  12.             var $clicked = $(e.target);    //e.target 捕捉到触发的元素  
  13.             console.log(e.target.nodeName);  //结果为大写,用toLowerCase()  转换为小写  
  14.             e.target.nodeName.toLowerCase() == 'table' ? alert('我点中table了')  : $clicked.html();  //排除父元素的点击效果  
  15.         })  
  16.           
  17.   
  18.         // jQuery1.7的on绑定方法,替代了以往的bind、live等方法,内部自动含有事件委托机制  
  19.         // $(selector).on(event,childSelector,data,function,map)   on方法的语法  
  20.         // $(selector).on(event,childSelector,function(){})        on方法语法,绑定在父元素上 事件,子选择器,回调函数  
  21.         $("#myTable").on('click','td',function(){  
  22.             $(this).html();  
  23.         })  
  24.     })  
  25. </script>  
总结:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值