3

前言:撸完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级只支持一个事件处理程序,但也不是什么问题,如今只卖早餐的饭店不多了~~~

这次没有源代码,以上~


yangdepp
446 声望21 粉丝

只有那些疯狂的人才能引起我的兴趣,那些人疯狂地生活,疯狂地表达,同时对一切事物心怀渴望,他们毫无倦意,不屑于陈词滥调,只是燃烧,燃烧,燃烧。