【事件绑定的方式】兼容浏览器的事件监听器的设计
来源:互联网 发布:docker 查看数据库 编辑:程序博客网 时间:2024/06/06 07:26
一、兼容浏览器的事件监听器
主要是兼容IE8以前的浏览器,addEvent方法中介绍了三种绑定事件的方式,其中要注意:
(1)在IE的事件绑定方式中,事件处理函数里面的事件对象时挂在window上面的,所以获取event对象时需要利用window.event来获取
(2)addEventListener添加监听器时注意事件的冒泡和事件的捕获,即该方法的第三个参数,事件的冒泡和捕获注意的事项参见下文
(3)利用属性绑定事件只能为同一个类型的事件添加一个事件处理函数,其他的两种方式均可以为同一类型的事件添加多个处理函数。所以属性绑定事件移除时直接赋值null即可。
EventUnit={ addEvent:function(ele,type,handler){ if(ele.addEventListener) { ele.addEventListener(type,handler,false); } else if(ele.attachEvent) { ele.attachEvent('on'+type,handler); } else ele['on'+type]=handler; }, removeEvent:function (ele,type,handler) { if(ele.removeEventListener) ele.removeEventListener(type,handler); else if(ele.dispatchEvent()) ele.dispatchEvent('on'+type,handler); else ele['on'+type]=null; }, stopPropagation:function (ev) { if(ev.stopPropagation) ev.stopPropagation(); else ev.cancelBubble=true; }, preventDefault:function (ev) { if(ev.preventDefault)ev.preventDefault(); else ev.returnValue=false; }, getTarget:function(ev) { return ev.target||ev.srcElement; }, getEvent:function (ev) { var ev=ev||window.event; return ev; }}
二、事件的捕获和冒泡
1、基本概念
(1)在IE8+的浏览器以及谷歌等浏览器中事件的发生均有三个阶段:事件的捕获–》事件触发对象–》事件冒泡
(2)事件捕获:
当event.target触发事件时,事件首先会发生在捕获阶段,即从上到下执行阶段,当该元素的祖先元素注册了同类型的事件且事件时发生捕获阶段(addEventListener的第三个参数设置为true,默认情况下所有事件时发生在冒泡阶段的,除了不能发生冒泡的事件)时,会先触发祖先元素的事件函数,一次向下执行。
(3)事件的冒泡则与事件的捕获的发生过程想法,事件的执行过程时从event.target向上冒泡执行的,不能冒泡的事件有:mouseenter/mouseleave/focus/blur/load等
2、事件冒泡捕获的具体情况
在同一个元素上注册同一类型事件的两种处理方式的回调函数,即既有冒泡的回调也有捕获的回调
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> #one{ width:400px; height:400px; border:2px solid red; } #two{ width:300px; height:300px; border:2px solid blue; } #three{ width:200px; height:200px; border:2px solid chartreuse; } #four{ width:100px; height:100px; border:2px solid rosybrown; } </style></head><body><div id='one'> <div id='two'> <div id='three'> <div id='four'> </div> </div> </div></div><script type='text/javascript'> var one=document.getElementById('one'); var two=document.getElementById('two'); var three=document.getElementById('three'); var four=document.getElementById('four'); one.addEventListener('click',function(){ alert('one,bubble'); },false); one.addEventListener('click',function(){ alert('one,capture'); },true); two.addEventListener('click',function(){ alert('two,bubble'); },false); two.addEventListener('click',function(){ alert('two,capture'); },true); three.addEventListener('click',function(){ alert('three,capture'); },true); four.addEventListener('click',function(){ alert('four'); },true);</script></body></html>
(1)点击元素只注册一种类型事件(捕获或者冒泡)
如果点击的是元素three,则执行的结果是:one,capture –> two,capture –> three,bubble–> two ,bubble–> one ,bubble
由此可以看出事件是严格遵循事件的处理的三个阶段的
(2)当点击的元素本身既具有捕获和冒泡事件时(点击two)
程序的执行结果是:one,capture –> two,bubble –> two,capture–>one,bubble
是不是看到这样的执行结果你觉得很奇怪,为什么two,bubble会先于two,capture呢?原因是在当前点击的元素上如果同时注册有捕获和冒泡事件其执行顺序是按照注册的先后顺序,先注册,先执行。所以才出现了这样的结果,你可以交换two事件的注册顺序后,继续点击two看看效果。当你点击one时就会发现执行的顺序也是按照注册的顺序执行的。
3、利用事件冒泡实现事件代理
同一类型的事件当在对个子元素上进行添加绑定时,会添加代码的冗余度,同时使得代码的可读性变差,因而可以利用时间的冒泡的方式将该事件绑定在其公共的父元素上,减少代码,同时当动态添加子元素时,也可以为该元素绑定上事件,如果是采用原始的方式,则动态添加的元素上将不会有时间处理函数。
在下面的代码中可以做测试,放开注释的部分既可以看到效果,如果要对比可以参见我的另一篇博客阿里前端内推笔试题
<!DOCTYPE html><html><head> <meta charset="utf-8"> <!--code here--> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, minimal-ui"> <meta name="format-detection" content="telephone=no"> <title>demo</title> <style> * { padding: 0; margin: 0;} .record-head{width:100%} .head, li div { display: inline-block; width: 20%; text-align: center; } li .id, li .sex, .id, .sex { width: 10%; } li .name, .name { width: 10%; } li .tel, .tel { width: 20%; } .del,.user-delete { width:10%; } ul { list-style: none; } .user-delete { cursor: pointer; } </style></head><body><div id="J_container"> <div class="record-head"> <div class="head id">序号</div> <div class="head name">姓名</div> <div class="head sex">性别</div> <div class="head tel">电话号码</div> <div class="head province">省份</div> <div class="head del">操作</div> </div> <ul id="J_List"> <li> <div class="id">1</div> <div class="name">张三</div> <div class="sex">男</div> <div class="tel">13788888888</div> <div class="province">浙江</div> <div class="user-delete">删除</div> </li> <li> <div class="id">2</div> <div class="name">李四</div> <div class="sex">女</div> <div class="tel">13788887777</div> <div class="province">四川</div> <div class="user-delete">删除</div> </li> <li> <div class="id">3</div> <div class="name">王二</div> <div class="sex">男</div> <div class="tel">13788889999</div> <div class="province">广东</div> <div class="user-delete">删除</div> </li> </ul></div><script> class Concat{ constructor(){ this.init(); } init(){ let Ul = document.querySelector("#J_List"); /*利用代理模式绑定事件,一则可以避免使用循环绑定, 二对于动态添加元素也可以触发事件, 但是有个问题是点击ol其他的位置可能会导致事件的响应,所以可以根据功能进行权衡,选择哪一种方式*/ Ul.addEventListener("click",(e) => { Ul.removeChild(e.target.parentNode); },false) } } new Concat(); /*测试用的,动态添加事件*/// let li = document.createElement("li");// li.innerHTML = ` <div class="id">3</div>// <div class="name">三二</div>// <div class="sex">男</div>// <div class="tel">13788889999</div>// <div class="province">广东</div>// <div class="user-delete">删除</div>`;// let ul = document.querySelector("#J_List");// ul.appendChild(li);</script></body></html>
- 【事件绑定的方式】兼容浏览器的事件监听器的设计
- 兼容浏览器的js事件绑定函数
- 兼容各个浏览器版本的事件监听器工具
- 关于怎么绑定Jquery 的scroll事件(兼容浏览器)
- 浏览器兼容的事件处理
- 感知SessioSession 绑定的事件监听器
- 兼容绑定事件的3种方法
- 自定义绑定事件的兼容讨论
- DOM2级事件绑定的兼容处理
- 事件监听器的4种实现方式
- 兼容各浏览器的窗口关闭事件
- 浏览器兼容之聚焦相关的事件
- 跨兼容浏览器的事件处理程序
- Java事件处理机制-事件监听器的实现方式
- Java事件处理机制-事件监听器的实现方式
- Java事件处理机制-事件监听器的实现方式
- Servlet的事件监听器
- Servlet的事件监听器
- angular路由跳转,并获取参数问题
- 流行编程语言的详细对比(3)--基本数据类型和字符串处理
- 进程和线程
- 使用vue中路由router-link中包含a标签
- Linux下的.so文件编写
- 【事件绑定的方式】兼容浏览器的事件监听器的设计
- 【HDU6146】【2017百度之星复赛-C】Pokémon GO(动态规划)(dp)
- DQN起源,原理,核心理解
- 高版本vtk 的MFC显示
- java 打印流(PrintStream,PrintWriter)
- POJ 1163 The Triangle
- Java 发送邮件
- 配置php
- Yii session 和 cookie