1、事件就是用户或浏览器自身执行的某种动作。
2、事件处理程序(或事件监听器)就是响应某个事件的函数。
HTML事件处理程序
//HTML中定义的事件处理程序包含要执行的具体动作
//这个值是JavaScript,所以不能再其中使用未经转义的HTML语法字符,例如& "" < >
<input type="button" value="确定" onclick="alert('clicked')" />
<input type="button" value="确定" onclick="alert("clicked")" />
//HTML中定义的事件处理程序也可以调用在页面其他地方定义的脚本
<script type="text/javascript">
function showMessage() {
alert("Hello world!");
}
</script>
<input type="button" value="确定" onclick="showMessage()" />
缺点:
-
存在一个时差问题。因为用户可能会在HTML元素一出现在页面上就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件。
- 为此,很多HTML事件处理程序会被封装在一个try-catch块中,以便用户不会看到JavaScript错误,因为在浏览器有机会处理错误之前,错误就被捕获了。
<input type="button" value="确定" onclick="try{showMessage()}catch(ex){}"/>
- 为此,很多HTML事件处理程序会被封装在一个try-catch块中,以便用户不会看到JavaScript错误,因为在浏览器有机会处理错误之前,错误就被捕获了。
这样扩展事件处理程序的作用域链在不同浏览器中会导致不同结果。不同JavaScript引擎遵循的标识符解析规则略有差异,很可能会在访问非限定对象成员时出错。
HTML与JavaScript代码紧密耦合,如果要更换事件处理程序就要改动两个地方:HTML代码和JavaScript代码。(着正是许多开发人员摒弃HTML事件处理程序,转而使用JavaScript指定事件处理程序的原因所在。)
DOM0 级事件处理程序
通过JavaScript指定事件处理程序的传统方式:
将一个函数赋值给一个事件处理程序属性。
优点:
- 简单。
- 具有跨浏览器的优势。
每个元素(包括window和document)都有自己的事件处理程序属性,这些属性通常全部消协。将这种属性的值设置为一个函数,就可以指定事件处理程序:
var btn = document.getElementById("myBtn");
btn.onclick = function () {
alert(this.id); //myBtn
}
使用DOM0 级方法指定的事件处理程序被认为是元素的方法。因此,是在元素的作用域中运行的,即程序中的this引用当前元素。
也可以删除通过 DOM0 级方法指定的事件处理程序:
btn.onclick = null; //删除事件处理程序
DOM2 级事件处理程序
定义了两个方法:
- addEventListener()
- removeEventListener()
addEventListener()方法
/**
* addEventListener()
* param:
* param1——要处理的事件名
* param2——作为事件处理程序的函数
* param3——一个布尔值:
* true,表示捕获阶段调用事件处理程序;
* false,表示冒泡阶段调用事件处理程序。
*/
var btn = document.getElementById("myBtn");
btn.addEventListener("click",function () {
alert(this.id);
},false);
btn.addEventListener("click",function () {
alert("hello world");
},false);
使用DOM2 级方法添加事件处理程序的主要好处就是可以添加多个事件处理程序,按照添加它们的顺序触发。
removeEventListener()
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。
通过addEventListener()添加的匿名函数将无法移除。
var btn = document.getElementById("myBtn");
btn.addEventListener("click",function () {
alert(this.id);
},false);
//.....
btn.removeEventListener("click",function(){ //没有用!!!
alert(this.id);
},false);
//修改后:
var btn = document.getElementById("myBtn");
var handler = function(){
alert(this.id);
};
btn.addEventListener("click",handler,false);
//.....
btn.removeEventListener("click",handler,false);
IE 事件处理程序
IE 实现了与 DOM 中类似的两个方法:
- attachEvent()
- detachEvent()
这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。
由于 IE8 及更早版本只支持事件冒泡,所以通过 attachEvent() 添加的事件处理程序都会被添加到冒泡阶段。
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
console.log("Clicked");
});
注意,attachEvent() 的第一个参数是 "onclick",而非 DOM 的 addEventListener() 方法中的 "click"。
在 IE 中使用 attachEvent() 与使用 DOM0 级方法的主要区别:事件处理程序的作用域。
- 在使用 DOM0 级方法的情况下,事件处理程序会在其所属元素的作用域内运行;
- 在使用 attachEvent() 方法的情况下,事件处理程序会在全局作用域中运行,因此 this 等于 window。
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
console.log(this === window); // true
});
attachEvent() 方法也可以用来为一个元素添加多个事件处理程序。不过,与 DOM 方法不同的是,这些事件处理程序不是以添加它们的顺序执行,而是以相反的顺序被触发。
使用 attachEvent() 添加的事件可以通过 detachEvent() 来移除,条件是必须提供相同的参数。与 DOM 方法一样,这也意味着添加的匿名函数将不能被移除。不过,只要能够将对相同函数的引用传给 detachEvent(),就可以移除相应的事件处理程序。
支持 IE 事件处理程序的浏览器有 IE 和 Opera。
跨浏览器的事件处理程序
要保证处理事件的代码能在大多数浏览器下一致地运行,只需关注冒泡阶段。
var EventUtil = {
//addHandler() 方法接受3个参数:要操作的元素、事件名称和事件处理程序函数。
addHandler: 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;
}
},
//removeHandler() 方法接受3个参数:要操作的元素、事件名称和事件处理程序函数。
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;
}
}
};
这两个方法首先都会检测传入的元素中是否存在 DOM2 级方法。如果存在 DOM2 级方法,则使用该方法:传入事件类型、事件处理程序函数和第三个参数 false(表示冒泡阶段)。如果存在的是 IE 的方法,则采取第二种方案。注意,为了在 IE8 及更早版本中运行,此时的事件类型必须加上 "on" 前缀。最后一种可能就是使用 DOM1 级方法(在现代浏览器中,应该不会执行这里的代码)。