事件是用户或者游览器自身执行的某种动作,诸如click,load,mouseover,都是时间的名称。响应某事件的函数就叫做事件处理程序(或者事件侦听器),事件处理程序的名字往往以'on'开头,比如click事件的事件处理程序是onclick,load时间的是onload。
为事件指定处理程序的方式有好几种:
1. html事件处理程序
<button id = 'mybutton1' onclick = 'alert("button1")' >Button1</button>
<button id = 'mybutton2' onclick = 'handleClick()' >Button2</button>
<script type = 'text/javascript'>
function handleClick(){
alert("button2");
}
</script>
这里特别一个问题,事件处理程中的代码在执行时,有权访问全局作用域中的任何代码。
但在html中指定事件处处理程序有两个缺点:
1. 时差问题。
2. html与javascript代码紧密耦合
第二点比较容易理解,这里重点讲下第一点,比如:
<html>
<head>
<title>Test UI Thread</title>
<script type = 'text/javascript'>
var handleClick = null;
setTimeout(function(){
handleClick = function (){
alert("button2");
}
},10000)
</script>
</head>
<body>
<div>
<button id = 'mybutton2' onclick = 'handleClick()' >Button2</button>
</div>
</body>
</html>
在段代码在页面刚出现时点击按钮是没有用的,10s后再点击才能触发相应事件,这里因为用户可能会在hmtl元素一出现就触发,但当时的事件处理程序可能尚不具备执行条件,这样就会报错。
由于以上两个缺陷,好的开发者应该摒弃这种事件处理程序。
2. DOM0级事件处理程序
通过Javascript制定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。这种方法至今仍然为所有现代游览器所支持,一是因为简单,而是跨游览器。每个元素(包括window和document)都有自己的事件处理程序属性,这些属性通常全部小写,例如onclick。将这种属性的值设置为一个函数,就可以指定事件处理程序。
具体如下:
<button id = 'mybutton3' >Button3</button>
<script type = 'text/javascript'>
var bn3 = document.getElementById('mybutton3');
bn3.onclick = function(){
alert('button3');
}
</script>
同样的道理,在这些代码运行以前不会指定事件处理程序,
特别强调的是,使用DOM0级方法指定的事件处理程序被认为是元素的方法,因此,这时候的事件处理程序在元素的作用域中运行;换句话说,程序中的this引用当前元素。比如还是上例,代码换成:
var bn3 = document.getElementById('mybutton3');
bn3.onclick = function(){
alert(this.id);// mybutton3
}
这时就会显示 mybutton3
可以在事件处理程序中通过this访问元素的任何属性和方法,以这种方式添加的事件处理程序都在事件流的冒泡阶段被处理。
当然只要像下面这样将事件处理程序属性设置为null,即可删除通过DOM0级方法指定的时间处理程序。
bn3.onclick = null;
3. DOM2级事件处理程序
“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventLister()。所有DOM节点中都包含这两个方法,并且他们都接受3个参数:要处理的事件名,作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕捉阶段调用事件调用事件处理程序,如果是false,表示在冒泡阶段调用事件处理程序。比如:
<button id = 'mybutton4' >Button4</button>
<script type = 'text/javascript'>
var bn4 = document.getElementById('mybutton4');
/*
* 最后一个参数布尔值
* true: 捕捉阶段调用事件处理程序
* false: 在冒泡阶段调用事件处理程序
* 大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种游览器
*/
bn4.addEventListener('click',function(){
alert('button4');
alert(this.id);
},false);
</script>
通过addEventListener()添加的时间处理程序只能使用removeEventListener()来移除;移除时传入的参数和添加处理程序时使用的参数相同。这意味着通过addEventListener()添加的匿名函数将无法移除,比如:
var bn4 = document.getElementById('mybutton4');
bn4.addEventListener('click',function(){
alert('add event listener of button4');
},false);
//没有用
bn4.removeEventListener('click',function(){
alert('remove event listener of button4');
});
这段代码之所以没有起作用是因为实际上,第二个参数与addEventListener()中的那个是完全不同的函数。正确的做法:
var hadler = function(){
alert('add event listener of button4');
};
bn4.addEventListener('click',hadler,false);
//有用
bn4.removeEventListener('click',hadler,false);