JS事件

一、基本概念

1、事件冒泡
IE的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档)。

2、事件捕获
Netscape Communicator团队提出的另一种事件流叫做事件捕获。事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前捕获它。

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

二、事件处理程序

1、HTML事件处理程序

<input type="button" value="Click me" onclick="alert('Clicked')"/>

在HTML中定义的事件处理程序可以包含要执行的具体动作,也可以调用在页面其他地方定义的脚本

<script type="text/javascript">
    function showMessage(){
        alert("Hello world");
    }
<script/>
<input type="button" value="Click Me" onclick="showMessage()"/>

事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码。

2、DOM0级事件处理程序
通过JavaScript指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序。

var btn=document.getElementById("myBtn");
btn.onclick=function(){
    alert(this.id); //"myBtn"
};

btn.onclick=null; //删除事件处理程序

这时候的事件处理程序是在元素的作用域中运行,所以会返回myBtn。

3、DOM2级事件处理程序
“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。
所有DOM节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。
最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。

var btn=document.getElementById("mybtn");
btn.addEventListener("click",function(){
    alert(this.id);
 },false);
 btn.addEventListener("click",function(){
    alert("Hello world");
 },false);

这里添加的事件处理程序也是在其依附的元素的作用域中运行。使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。这两个事件处理程序会按照添加它们的顺序触发。

通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。这也意味着通过addEventListener()添加的匿名函数将无法移除。

var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
    alert(this.id);
},false);
//这里省略了其他代码

btn.removeListener("click",function(){  //没有用!
    alert(this.id);
},false);
var btn=document.getElementById("myBtn");
var handler=function(){
    alert(this.id);
};
btn.addEventListener("click",handler,false);
//这里省略了其他代码

btn.removeListener("click",handler,false); //有效

4、IE事件处理程序
attachEvent()和detachEvent(),只接受两个参数。通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。
在使用attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此this等于window.

var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
    alert(this===window);    //true
});
var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
    alert("Clicked");    //该事件后触发
});
btn.attachEvent("onclick",function(){
    alert("Hello world!");   //该事件先触发
});

移除事件:

var btn=document.getElementById("myBtn");
var handler=function(){
    alert("Clicked");
};
btn.attachEvent("onclick",handler);
//这里省略了其他代码

btn.detachEvent("onclick",handler); 

5、跨浏览器的事件处理程序

var EventUtil={
 addHandler:function(element,type,handler){
    if(element.addEventListener){
     element.addEventListerner(type,handler,false);
     }else if(element.attachEvent){
         element.attachEvent("on"+type,handler);
     }else{
        element["on"+type]=handler;
    }
  },
 removerHandler: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;
   }
 }
};

可以像下面这样使用EventUtil对象:

var btn=document.getElementById("myBtn");
var handler=function(){
    alert("Clicked");
};

EventUtil.addHandler(btn,"click",handler);
//这里省略了其他代码
EventUtil.removeHandler(btn,"click",handler);

三、事件对象

1、DOM中的事件对象
兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0级或DOM2级),都会传入event对象。

2、IE中的事件对象
与访问DOM中的event对象不同,要访问IE中的event对象有几种不同的方式,取决于指定事件处理程序的方法。在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在。

3、跨浏览器的事件对象
IE中的event对象的全部信息和方法DOM对象中都有,只不过实现方式不一样。

var EventUtil={
    addHandler:function(element,type,handler){
        //省略的代码
    },
    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;
        }
    },
    removeHandler:function(element,type,handler){
            //省略的代码
        },
    stopPropagation:function(event){
        if(event.stopPropagation){
            event.stopPropagation();
        }else{
            event.cancelBubble=true;
        }
    }
};

1、使用第一个方法:

btn.onclick=function(event){
 event=EventUtil.getEvent(event);
};

2、使用第二个方法:

btn.onclick=function(event){
 event=EventUtil.getEvent(event);
 var target=EventUtil.getTarget(event);
};

3、使用第三个方法:

var link=document.getElementById("myLink");
link.onclick=function(event){
 event=EventUtil.getEvent(event);
 EventUtil.preventDefault(event);
};

4、使用第四个方法:

var btn=document.getElementById("myBtn");
btn.onclick=function(event){
 alert("Clicked");
 event=EventUtil.getEvent(event);
 EventUtil.syopPropagation(event);
};

document.body.onclick=function(event){
    alert("Body clicked");
};

四、事件委托

对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。以下面的HTML代码为例:

<ul>
    <li id="goSomewhere">Go somewhere</li>
    <li id="doSomething">Do something</li>
    <li id="sayHi">Say hi</li>
</ul>

使用事件委托,只需要在DOM树中尽量最高的层次上添加一个事件处理程序,如下面的例子所示:

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;      
    }
});
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章