通过JavaScript指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。这种为事件处理程序赋值的方法是在第四代Web浏览器中出现的,而且至今仍然为所有现代浏览器所支持。原因一是简单,二是具有跨浏览器的优势。要使用JavaScript指定事件处理程序,首先必须取得一个要操作的对象的引用。每个元素(包括window和document)都有自己的事件处理程序属性,这些属性通常全部小写,例如onclick。将这种属性的值设置为一个函数,就可以指定事件处理程序,如下所示:
var btn=document.getElementById("myBtn"); btn.onclick=function(){ alert("Clicked"); }
在此,我们通过文档对象取得了一个按钮的引用,然后为它指定了onclick事件处理程序。但要注意,在这些代码运行之前不会指定事件处理程序,因此如果这些代码在页面中位于按钮后面,就有可能在一段时间内怎么单击都没有反应。使用DOM0级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中运行;换句话说,程序中的this引用当前元素。
var btn=document.getElementById("myBtn"); btn.onclick=function(){ alert(this.id); }
单击按钮显示的是元素的ID,这个ID是通过this.id取得的。不仅仅是ID,实际上可以在事件处理程序中通过this访问元素的任何属性和方法。以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。也可以删除通过DOM0级方法指定的事件处理程序,只要像这样将事件处理程序属性的值设置为null即可:
btn.onclick=null; //删除事件处理程序
将事件处理程序设置为null之后,再单击按钮将不会有任何动作发生。如果你使用HTML指定事件处理程序,那么onclick属性的值就是一个包含着在同名HTML特性中指定的代码的函数。而将相应的属性设置为null,也可以删除以这种方式指定的事件处理程序。
DOM2级事件定义了两个方法,用于处理指定和删除事件处事程序的操作:addEventListener()和removeEventListener()。所有DOM节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。要在按钮上为click事件添加事件处理程序,可以使用下列代码:
var btn=document.getElementById("myBtn"); btn.addEventListener("click",function(){ alert(this.id); },false);
上面的代码为一个按钮添加了onclick事件处理程序,而且该事件会在冒泡阶段被触发(因为最后一个参数是false)。与DOM0级方法一样,这里添加的事件处理程序也是在其依附的元素的作用域中运行。使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。来看下面的例子:
var btn=document.getElementById("myBtn"); btn.addEventListener("click",function(){ alert(this.id); },false); btn.addEventListener("click",function(){ alert(this.firstChild.nodeValue); },false);
这里为按钮添加了两个事件处理程序。这两个事件处理程序会按照添加它们的顺序触发,因此首先会显示元素的ID,其次会显示元素所包含的文本。通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。这也意味着通过addEventListener()添加的匿名函数将无法移除,如下面的例子所示:
var btn=document.getElementById("myBtn"); btn.addEventListener("click",function(){ alert(this.id); },false); btn.removeEventListener("click",function(){//没有用! alert(this.id); },false);
在这个例子中,我们使用addEventListener()添加了一个事件处理程序。虽然调用removeEventListener()时看似使用了相同的参数,但实际上,第二个参数与传入addEventListener()中的那一个是完全不同的函数。而传入removeEventListener()中的事件处理程序函数必须与传入addEventListener()中的相同,如下面的例子所示。
var btn=document.getElementById("myBtn"); var handler=function(){ alert(this.id); }; btn.addEventListener("click",handler,false); btn.removeEventListener("click",handler,false);//有效!
重写后的这个例子没有问题,是因为在addEventListener()和removeEventListener()中使用了相同的函数。大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。最好只在需要在事件到达目标之前截获它的时候将事件处理程序添加到捕获阶段。如果不是特别需要,我们不建议在事件捕获阶段注册事件处理程序。IE9、Firefox、Safari、Chrome和Opera支持DOM2级事件处理程序。