事件
来源:互联网 发布:邮箱服务器搭建软件 编辑:程序博客网 时间:2024/05/03 07:37
事件流
事件流:从页面接收事件的顺序
IE和Netscape提出了完全相反的事件流概念
事件冒泡(IE)
点击事件会沿着dom树向上传递
例如:div->body->html->document
事件捕获(NetScape)
点击事件沿着dom树向下传递
例如:document->html->body->div
现在主流的都是支持事件冒泡
dom事件流
dom2将事件流分为三个阶段:捕获阶段,处理阶段,冒泡阶段
即使dom2明确要求捕获阶段不应该涉及事件目标,但是在很多浏览器上都会在捕获阶段触发目标事件。
于是,有两个阶段可以在目标对象上操作事件
事件处理程序
事件处理程序名称=on+事件名称(click,load)
html事件处理程序
事件处理程序有权访问 全局环境中的所有代码
<input type = 'button' value='clickMe' onclick='alert('click')'>
这里我访问一个全局变量myname:
<body><script type="text/javascript"> var myname = 'geguo';</script><input type="button" value="clickMe" onclick="console.log(myname)"></body>
每点击一下 控制台输出 geguo
事件对象:
在元素(input)中定义一个事件处理程序有一个好处,可以获取到元素的所有属性,这些属性都会封装到一个函数中(this指向这个函数对象,事件处理程序中可以直接访问),这个函数有一个局部变量,也就是事件对象;这个事件对象event是默认创建的,可以在事件处理程序中直接访问。
dom0事件处理程序
在Js代码中添加事件处理程序,当js没有被执行到的时候,点击不会反应。
<input type="button" value="clickMe"><script type="text/javascript"> var mbts = document.getElementsByTagName('input'); var mb=mbts[0]; mb.onclick=function(){ console.log(this.value); };</script>
这里的this指向的是元素对象(该对象中有一个event属性值就是事件对象)
删除处理程序: mb.onclick=null;
Dom2级事件处理程序
上述两种方法有一个明显的缺点:click事件只能添加一个事件处理程序,然而DOM2可以为同一事件添加多个处理程序
- addEventListener(‘事件名称(非事件处理程序名称)’,事件处理程序(函数),boolan(true捕获阶段处理|false冒泡阶段处理))共三个参数
- removeEventListener(‘事件名称’,之前添加的处理函数,boolean)
- 第三个参数一般是false,通常建议通过冒泡方式处理
<input type="button" value="clickMe"><script type="text/javascript"> var mbts = document.getElementsByTagName('input'); var mb=mbts[0];var handle = function(){ console.log(this.value); }; mb.addEventListener('click',handle,false); // mb.addEventListener('click',handle2,false);还可以添加一个函数 //移除后点击没有反应了;注意这里的事件处理函数是同一个函数对象 mb.removeEventListener('click',handle,false);</script>
IE事件处理程序
支持IE事件处理程序的只要IE和Opera
- attachEvent(’事件处理程序名’(非事件名),处理函数);
- detachEvent(同上)
与dom2级处理程序的区别在于:
- attach方式支持的浏览器只有两种
- 它们的第一个参数不同
相同点:
他们都支持添加多个事件处理程序,不过执行的顺序与添加的顺序不同。
<input type="button" value="clickMe"><script type="text/javascript"> var mbts = document.getElementsByTagName('input'); var mb=mbts[0];var handle = function(){ console.log(this.value); }; mb.attachEvent('onclick',handle);
Chrome根本不支持attachEvent()
在 IE 中使用 attachEvent() 与使用 DOM0 级方法的主要区别
主要在于事件处理程序的作用域。
在使用 DOM0 级方法的情况下,事件处理程序会在其所属元素的作用域内运行;
在使用 attachEvent() 方法的情况下,事件处理程序会在全局作用域中运行,因此 this 等于 window 。
兼容浏览器事件处理工具类
默认使用dom0
最先检测dom2
其次判断IE
var EventUtil={ addHandler:function(element,type,handle){ if (element.addEventListener) { element.addEventListener(type,handle,false); }else if(element.attachEvent){ element.attachEvent('on'+type,handle); }else{ element['on'+type]=handle; } }, removeHandle:function(){ if (element.addEventListener) { element.removeEventListener(type,handle,false); }else if(element.attachEvent){ element.detachEvent('on'+type,handle); }else{ element['on'+type]=null; } }};EventUtil.addHandler(mb,'click',handl);
事件对象
var handl = function(){ //this指向元素所在作用域对象 console.log(this.value); // 这里的event 可以直接访问 console.log(event.type); // 默认的事件处理程序的第一个参数也是事件对象 console.log(arguments[0].type); };
兼容DOM的浏览器会将一个event对象作为事件处理程序的第0个参数传入。
- 在事件处理程序中可以直接访问event对象(event作为window的属性)
- arguments[0]其实就是event对象
- 可以将event对象传入:function(event){ event.type}
event对象的成员属性
target Element类型:事件的目标(具体哪个元素的事件)
type string类型:事件类型(click,move)
currentTarget Element类型:当前正在处理事件的那个元素
stopPropagation 阻止传递
preventDefault 取消事件
//将点击事件添加到body上EventUtil.addHandler(document.body,'click',handle);
var handle = function(event){ console.log(event.currentTarget === document.body); console.log(this === document.body); console.log(event.targt === mb);
因为事件处理程序都注册在body上,所以this和currentTarget都指向body元素,而真正的目标targe是指向button(我怎么测试不是呢?)
IE中的Event对象
- type
- srcElement dom中的target
- returnValue 取消事件
- cancelBubble 取消事件冒泡
IE中访问event对象
- dom0级事件只能通过window.event 访问
- dom2级事件可以通过event参数去访问
- IE中没有内置event对象
<script type="text/javascript"> var btn = document.getElementById('button'); // IE 中DOM0级事件访问event只能通过window.event btn.onclick = function(){ var event = window.event;//在DOM0中需要如此访问 alert(event.type); //"click" 直接访问无效 }; // 这是DOM2级 btn.attachEvent("onclick", function(event){ alert(event.type); });</script>
跨浏览器事件对象
因为IE浏览器和其他浏览器的属性不一样,所以需要封装一个类来专门处理他们之间的不同
var EventUtil={ addHandler:function(element,type,handle){ if (element.addEventListener) { element.addEventListener(type,handle,false); }else if(element.attachEvent){ element.attachEvent('on'+type,handle); }else{ element['on'+type]=handle; } }, removeHandle:function(element,type,handle){ if (element.addEventListener) { element.removeEventListener(type,handle,false); }else if(element.attachEvent){ element.detachEvent('on'+type,handle); }else{ element['on'+type]=null; } }, getEvent:function(event){ //IE 的dom0事件只支持window.event,不支持通过参数传递 //IE的dom2和其他浏览器都支持通过event参数方式访问 return event?event:window.event; }, getTarge:function(event){ // IE 的dom0 不支持event参数方式访问 // return event.targt||event.srcElement; return this.getEvent(event).targt||this.getEvent(event).srcElement; }, // 取消该事件(和移除该事件有什么不一样么) preventDefault:function(event){ var event = this.getEvent(event); if (event.preventDefault){ event.preventDefault(); } else { //IE中的 event.returnValue = false; } }, // 阻止事件冒泡 stopPropagation:function(event){ var event = this.getEvent(event); if (event.stopPropagation) { event.stopPropagation(); }else{ event.cancelBubble = true; }; }};
这个工具类如何使用
DOM0级事件
mb.onclick=function(event){ var type =EventUtil.getTarge(event).type; alert(type); }
DOM2级事件
EventUtil.addHandler(mb,'click',function(event){ var type=EventUtil.getTarge(event).type; alert(type);})
在IE和Chrome浏览器中测试均有效;
事件类型
UI事件
焦点事件
鼠标与滚轮事件
键盘与文本事件
复合事件
变动事件
HTML5事件
设备事件
触摸与手势事件
性能与优化
添加过多的函数会占用过大的内存,同时也会影响页面加载的速度
利用事件冒泡的特性,可以通过一个事件处理程序来处理某一类型的事件;
<ul id="myLinks"><li id="goSomewhere">Go somewhere</li><li id="doSomething">Do something</li><li id="sayHi">Say hi</li></ul>
要给三个item添加点击事件传统写法:
var item1 = document.getElementById("goSomewhere");var item2 = document.getElementById("doSomething");var item3 = document.getElementById("sayHi");EventUtil.addHandler(item1, "click", function(event){location.href = "http://www.wrox.com";});EventUtil.addHandler(item2, "click", function(event){document.title = "I changed the document's title";});EventUtil.addHandler(item3, "click", function(event){alert("hi");});
这有一个明显缺点:代码冗余
使用代理方式可以解决这个问题:
var list = document.getElementById("myLinks");EventUtil.addHandler(list, "click", function(event){event = EventUtil.getEvent(event);var target = EventUtil.getTarget(event);switch(target.id){case "doSomething":document.title = "I changed the document's title";break;case "goSomewhere":location.href = "http://www.wrox.com";break;case "sayHi":alert("hi");break;}});
尽量在dom书最高层次的节点上添加该点击事件。
这里的target就是用户通过鼠标点击的那个控件,通过冒泡会传递到父节点上,父节点会处理。事件被处理后还会继续冒泡么?
移除事件处理程序
如果知道某个元素即将被移除那些请先移除它的事件处理程序
<div id="myDiv"><input type="button" value="Click Me" id="myBtn"></div><script type="text/javascript">var btn = document.getElementById("myBtn");btn.onclick = function(){//先执行某些操作document.getElementById("myDiv").innerHTML = "Processing..."; //麻烦了!};</script>
以上:当按钮点击时在自己的处理程序中把自己移除了
这种做法,虽然移除了按钮元素,但是事件处理程序依然在元素的作用域中运行,持有这个元素的引用。导致该元素无法被真正的释放。
正确的写法应该是:
btn.onclick = function(){//先执行某些操作btn.onclick = null; // 移除事件处理程序document.getElementById("myDiv").innerHTML = "Processing...";};
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- 事件
- RecyclerView android5.0之后替换listview、gridview
- Jena本体操作函数简要说明
- 网络请求部分详细解析
- 从jdbc的resultset中获得列名
- Android之Zxing扫描二维码 简单式集成
- 事件
- 浅析分布式系统
- plsql工具中代码提示的设置及保存密码设置
- Opencv决策树分类器应用
- 矩阵分析之Givens Reduction
- 去哪儿2015研发工程师——首个重复字符
- C++容器适配器使用
- 从头开始学java<三>
- EasyUI datagrid动态加载json数据