事件流

事件流描述的是页面接收事件的顺序.IE的事件流是冒泡流,而 Netscape Communicator的事件流是事件捕获流.

事件冒泡是指事件开始时由最具体的元素,然后向上传播到较为不具体的节点.所有现代浏览器都支持事件冒泡,IE9,Firefox,chrome,safari则将事件一直冒泡到window对象.

事件捕获是不太具体的节点应该更早接收到事件,而具体的节点应该最后接收到事件.

DOM事件流
DOM2级事件流规定的事件流包括三个阶段: 事件捕获阶段 处于目标阶段 事件冒泡阶段

事件处理程序

HTML事件处理程序

on+事件名(例如onclick)作为事件目标的属性,属性值为事件处理程序,在html中定义的事件处理程序可以包含要执行的具体动作,也可以调用页面其他地方定义的脚本.

<input type="button" value='click me' onclick="alert('Clicked');"/>
<input type="button" value="click me" onclick="showMessage()"/>
function showMessage(){
    alert("Hello world!");
}

DOM0级事件处理程序

DOM0级事件处理程序是在js中处理的,它的优势是简单,目前所有浏览器支持良好,并且不会与html代码产生耦合.

 var btn =  document.getElementById('btn');
 btn.onclick  = function(){
     alert('clicked me!');
 };

这里是把事件处理程序赋值给了DOM对象的属性,这个属性的构成是on+事件名,比如onclick`onblur`onload.

DOM2级事件处理程序

DOM2级事件定义了两个方法addEventListener removeEventListener,这两个方法都接收三个参数.第一个参数代表事件类型;第二个参数代表事件处理程序;第三个参数是指在冒泡阶段还是捕获阶段处理事件处理程序,如果为true代表捕获阶段处理,如果是false代表冒泡阶段处理.
IE9,google,Firefox兼容DOM2级事件处理程序.

    var btn = document.getElementById('btn');
    
    //事件处理程序
    function handler(){
        alert('click!');
    }
    
    //注册事件处理程序
    addEventListener('click',handler,false);
    
    //注销事件处理程序
    removeEventListener('click',handler,false);

注:添加匿名事件处理程序无法被注销

IE事件处理程序

IE8及以下浏览器不支持DOM2级事件处理程序,但也自己定义了attachEvent`detachEvent`两个方法,这两个方法只接受两个参数,因为IE8及以下版本不支持事件捕获,所以没有第三个参数.

var btn = document.getElementByID("btn");

    //事件处理程序
    function handler(){
        alert('click!');
    }
    
    //注册事件处理程序
    attachEvent('click',handler,false);
    
    //注销事件处理程序
    detachEvent('click',handler,false);

跨浏览器的事件处理程序

综合以上几种事件处理程序,我们封装出了一个跨浏览器的事件处理程序对象.

    var EventUtil ={
    
        //注册事件处理程序
        addEventHandler:function(element,type,handler){
        
            if(element.addEventListener){
                element.addEventListener(type,handler,false);
            }
            
            else if(element.attachEvent) {
                element.attachEvent('on'+type,handler);
            }
            
            else{
                element['on'+type]=handler;
            }
        },
        
        //注销事件处理程序
        removeEventHandler: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;
            }
        }
    };

    var btn = document.getElementById('btn'),
            handler=function(event){
                alert(this.value);
            };

    EventUtil.addEventHandler(btn,'click',handler);

事件对象

在触发DOM的某个事件时,会产生一个事件对象,这个对象包含着所有与事件相关的信息。包括导致事件的元素,事件的类型,以及其他与特定事件相关的信息.例如鼠标操作导致的事件对象中,包含鼠标位置的信息,键盘定义的事件中包含按下键相关的信息.所有浏览器支持event对象,但支持方式不同.

DOM中的事件对象

兼容DOM的浏览器会将一个event对象传入到事件处理程序中.DOM0和DOM2都会传入event. html事件处理程序也有event对象.

 var btn = document.getElementById("btn");
 
 btn.onclick = function(event){
     alert(event.type);
 }
 
 btn.addEventHandler('click',function(event){
     alert(event.type);
 },false);

触发的事件类型不一样,可用的属性和方法也不一样.不过所有事件的event对象都有公共成员,这里列出几个常用的属性和方法.

  1. 属性
    currentTarget 指向某个元素,事件处理程序发生在此元素上
    target 事件的目标
    type 事件类型
    eventPhase 事件所处阶段

  2. 事件
    preventDefault() 取消事件的默认行为
    stopPropagation() 取消事件的进一步冒泡或捕获
    在事件处理程序内部,对象this始终等于currentTarget的值.而target则只包含事件的实际目标.

IE中的事件对象

使用DOM0级事件处理程序时,event对象作为window对象的一个属性存在;
使用attachEvent()事件处理程序时,event对象作为参数传入.

跨浏览器的事件对象

var EventUtil = {

    //添加事件
    addEventHandler:function(element,type,handler){
        if(element.addEventListener){
            element.addEventListener(type,handler,false);
        }
        else if(element.attachEvent) {
            element.attachEvent('on'+type,handler);
        }
        else{
            element['on'+type]=handler;
        }
    },
    
    //移除事件
    removeEventHandler: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;
        }
    },
    
    //获取事件对象
    getEvent: function (event) {
        return event ? event : window.event;
    },
    
    //获取事件目标
    getTarget:function(event){
        return event.target || event.srcElement;
    },
    
    //阻止默认行为
    preventDefault:function(event){
        if(event.preventDefault){
            event.preventDefault();
        }
        else{
            event.returnValue = false;
        }
    },
    
    //阻止事件冒泡
    stopPropagation:function(event){
        if(event.stopPropagation)
        {
            event.stopPropagation();
        }
        else{
            event.cancelBubble=true;
        }
    }
};

使用以上定义的EventUtil对象,可以在所有浏览器中进行进行事件的添加,移除,获取事件对象,获取事件目标,阻止事件冒泡,阻止事件默认行为.


yuhualingfeng
1.7k 声望49 粉丝

前端极致追求者