前言:撸完CSS-DOM紧接着来撸DOM事件,事件总结完成后我要开始总结动画,然后用纯JS实现一个轮播图,前路漫漫,还有各种框架等着我~~~
本篇主要内容有:事件流 事件处理程序 跨浏览器事件处理程序
--------------------? 分割线---------------------
1.事件流
事件冒泡:事件开始时由最具体的元素(文档嵌套层次最深的节点)接收,然后逐级向上传播到较为不具体的节点。
事件捕获:不太具体的节点应该更早接收到事件,最具体的节点应该最后接收到事件。
2.DOM事件流
在W3C规范中:分三步(1、事件捕获;2、事件触发;3、事件冒泡);
在IE中:分两步(1、事件冒泡;2、事件触发)
在网景(Netscape):分两步(1、事件捕获;2、事件触发)
3.事件处理程序
(一)HTML事件处理程序
这个在《DOM编程艺术》中初步实现的图片库的总结(一)就有了运用,它的js代码嵌套在HTML中,如:想要实现在点击按钮时显示一个警告框,则可以这么写:
<input type="button" value="狠狠的点我" onclick="alert('clicked')"/>
缺点:
1.代码例子中的alert可以换成自己定义的函数,假如用户在页面加载后还没开始解析这个函数时就单击了按钮,这个时候就会引发错误,这时可以将事件处理程序封装在try-catch块中,上面的代码可以改为:
<input type="button" value="狠狠的点我" onclick="try{showsomething();}catch(ex){}"/>
2.HTML和js代码耦合性太强,如果要更换事件处理程序,就要改动两个地方。
(二)DOM 0级事件处理程序
每个元素(包括window和document)都有自己的事件处理程序属性,例如onclick,将这种属性值设置为一个函数,就可以指定事件处理程序,如下方代码:
//假如有一个按钮,先获取这个按钮元素
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert("你点我干啥!!!");
};
注意:以上代码在运行之前不会指定事件处理程序,换句话说就是如果这些代码插入在html文档中的最后,位于按钮之后,body标签之前,那么在文档解析这个函数之前,点击按钮时无效的。
优点:简单,具有跨浏览器的优势
特点:使用DOM 0级方法指定事件处理程序被认为是元素的方法,因此这个时候事件处理是在元素的作用域中进行运行,程序中的this指向当前元素。 来看下面一段代码:
var btn = document.getElementById("mybtn");
btn.onclick = function(){
alert(this.id); //this代表当前执行操作的元素btn,也就是id为mybtn的按钮
}
以上不仅仅可以访问元素的id属性,元素的任何属性和方法都可以通过this访问。以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。
(三)DOM 2级事件处理程序
DOM 2级事件定义了两个方法,分别用于处理指定和删除事件处理程序的操作:addEventListener()
和removeEventListener()
,
他们都接收三个参数:要处理的事件名、作为事件处理程序的函数、一个布尔值。
布尔值如果是true表示在捕获阶段调用事件处理程序,如果是false表示在冒泡阶段调用事件处理程序。
添加事件操作
如下代码:
var btn = document.getElementById("myBtn");
btn.addEventListener("click",function(){
alert(this.id);
},false);
btn.addEventListener("click",function(){
alert("你点我干啥!!!");
},false);
以上代码为一个按钮添加了一个onclick事件处理程序,注意里面参数传递的是"click"
,这个是跟DOM中的事件类型有关,后续再说。~~~
并且使用DOM 2级方法添加事件处理程序的好处是,可以添加多个事件处理程序,上面例子中首先会显示元素id,然后显示"你点我干啥!!!"。
删除事件操作
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除,移除时传入的参数与添加程序时使用的参数相同。这也就意味着通过addEventListener()添加的匿名函数将无法移除。如上面的例子,我增加以下代码将无法移除事件:
btn.removeEventListener("click",function(){
alert(this.id);
},false);
解决办法是,将上面的匿名函数赋值给一个变量,然后adddEventListener和 removeEventListener
传参数时传入这个变量就可以了。
重写这个函数如下:
var btn = document.getElementById("myBtn");
var handler = function(){
alert(this.id);
};
btn.addEventListener("click",handler,false);
btn.addEventListener("click",handler,false);
(4)跨浏览器的事件处理程序
----------------- 珍爱生命,远离IE ------------------
IE也实现了DOM中的类似的两个方法:attachEvent() 和detachEvent(),这两个方法接受相同的两个参数,事件处理程序名称与事件处理程序函数。
如下代码:
var btn = document.getElementById("mybtn");
btn.attachEvent("onclick",function(){ //你没看错,用的“onclick”!!!
alert("你又点我了!!!");
});
注意:
1.attachEvent()的第一个参数时“onclick”
2.使用attachEvent(),事件处理程序会在全局作用域中进行,因此this===window
3.添加多个事件时,事件处理程序不是以添加它们的顺序执行,而是以相反的顺序被触发。
4.使用detachEvent()来移除时,匿名函数同样不能移除,因此需要传递给函数相同的引用。
那么重点来了,可以封装一个对象解决跨浏览器进行事件处理,给这个对象起名叫:EventUtil,它有两个方法,分别进行事件添加和移除。
且看下面代码:
var EventUtil = {
//@handler是装载匿名函数的引用变量,里面装载的是具体要执行的函数逻辑
//@element是目标元素
//type代表的是DOM 2级的事件类型,因此在用IE或者DOM 0级前面要加“on”
addHandler: function (element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
elemet["on" + type] = handler; //如果上面两种都不行,就使用DOM 0级方法处理,直接在元素上添加onclick事件
}
},
removeHandler: function (element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null; ////如果上面两种都不行,就使用DOM 0级方法处理,直接赋值为null取消事件
}
}
};
定义好了,怎么使用呢?看下面~~~
var btn = document.getElementById("myBtn");
var handler = function(){
alert("你又点我了!!!");
};
//添加事件
EventUtil.addHandler(btn,"click",handler);
//移除事件
EventUtil.removeHandler(btn,"click",handler);
以上代码并没有考虑IE中的作用域问题,并且DOM 0级只支持一个事件处理程序,但也不是什么问题,如今只卖早餐的饭店不多了~~~
这次没有源代码,以上~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。