https://blog.csdn.net/z69183787/article/details/54019756
什么叫事件委托?他还有一个名字叫做事件代理,(时间代理 === 事件委托,现在才知道这两个是一个意思)
高程3上讲:事件委托即是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
借鉴其他大牛的一个例子,也为自己更好的理解一下:收快递例子
有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
两层意思:
1.现在委托前台的同事是可以签收的,即程序中的现有的dom节点是有事件的;
2.新员工也是可以被前台mm代为签收的,即程序中新添加的dom节点也是有事件的;
为什么要用事件委托???事件委托有什么好处???
一般来说,dom是需要有事件处理程序的,我们会直接给他事件处理程序就好了,那么如果是很多dom元素需要添加事件处理呢???
比如 100个li,每个li 都有相同的click点击事件,可能我们会有for循环的方法,来遍历所有li,然后为每个li添加绑定事件。
这么做毫无疑问的是对性能有很大的影响;
在js中,添加到页面上的事件处理程序的多少将直接关系到页面运行的整体性能,因为需要不断的与dom节点进行交互,访问dom次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间。
这就是性能优化,减少dom操作的原因;
- window.onload = function(){
- var oTa = document.getElementById("myTable");
- var aTd = oTa.getElementsByTagName('td');
- for(var i=0;i<aTd.length;i++){
- aTd[i].onclick = function(){
- aTd[i].style.background = 'red';
- }
- }
- }
如果采用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只交互一次,这样减少了dom交互次数,性能就会提升;
事件委托原理:
事件委托就是利用事件冒泡原理实现的!
事件冒泡:就是事件从最深节点开始,然后逐步向上传播事件;
例:页面上有一个节点树,div > ul > li > a
比如给最里面的a 加一个click 事件,那么事件就会一层一层的往外执行,执行顺序 a > li > ul > div, 有这样一个机制,当我们给最外层的div 添加点击事件,那么里面的ul , li , a 做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托他们父集代为执行事件;
里用父集做事件处理,当td被点击时,由于冒泡原理事件就会冒泡到table上,因此table上有点击事件,所以事件就会被触发;
当然单当点击table本身的时候也是会触发的;
如果我们只想让td触发而不想让table触发,怎么办呢???
Event对象提供了一个属性叫做target,可以返回事件的目标节点,我们称之为事件源,也就是说,target就可以表示当前事件操作的dom,但可能不是真正操作的dom,
存在兼容性问题:标准浏览器:event.target,IE浏览器:event.srcElement,
此时只是获取了当前节点的位置,但并不知道节点名称,这里我们用nodeName来获取具体是什么标签名,这个返回值是一个大写的,判断时需要转换为小写;
4个按钮,点击每一个做不同的动作,,,那么至少需要4次dom操作;
如果用事件委托,能进行优化吗?
事件委托写法
[javascript] view plain copy
- window.onload = function(){
- var myTable = document.getElementById("myTable");
- myTable.onclick = function (ev) {
- var ev = ev || window.event;
- var target = ev.target || ev.srcElement;
- if(target.nodeName.toLocaleLowerCase() == 'table'){
- switch(target.id){
- case 'add' :
- alert('添加');
- break;
- case 'remove' :
- alert('删除');
- break;
- case 'move' :
- alert('移动');
- break;
- case 'select' :
- alert('选择');
- break;
- }
- }
- }
- }
- <script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
- <script type="text/javascript">
- $(function(){
- $("#myTable td").click(function(){
- $(this).html(); //普通写法,如果有100个td元素,就要绑定100次事件,十分浪费性能
- })
- $("#myTable").click(function(e){ //这种点击方式怎么排除父元素????
- console.log(e.target);
- var $clicked = $(e.target); //e.target 捕捉到触发的元素
- console.log(e.target.nodeName); //结果为大写,用toLowerCase() 转换为小写
- e.target.nodeName.toLowerCase() == 'table' ? alert('我点中table了') : $clicked.html(); //排除父元素的点击效果
- })
- // jQuery1.7的on绑定方法,替代了以往的bind、live等方法,内部自动含有事件委托机制
- // $(selector).on(event,childSelector,data,function,map) on方法的语法
- // $(selector).on(event,childSelector,function(){}) on方法语法,绑定在父元素上 事件,子选择器,回调函数
- $("#myTable").on('click','td',function(){
- $(this).html();
- })
- })
- </script>
总结:
事件委托的优点:1.在页面dom元素较多的情况下,大大减少了dom操作,优化了性能;
2.值需要为一个父元素绑定事件,就可以管理他下面的所有子元素;
3。。。。。。啦啦啦啦,我也不知道啦
适用性:
适合:click 、mousedown、mouseup、keydown 、keyup、keypress
不适合:mouseover和mouseout虽然也有事件冒泡,但是处理他们要特别注意,因为需要经常计算他们的位置,处理起来不太容易,
focus、blur之类的本身就没有冒泡的特性,自然不能用事件委托;
借鉴博客园那位兄弟的文章!!!!