1."DOM2级事件"规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
在DOM事件流中,实际的目标在捕获阶段不会接收到事件。事件从document到<html>再到<body>后就停止了。下一个阶段是“处于目标阶段”,此时事件在<div>上发生,并在事件处理中被看成冒泡阶段的一部分。然后冒泡事件发生,事件又传播回原文档。
2.事件处理程序是指响应某个事件的函数
3.扩展动态函数作用域
<input type="button" value="Click Me" onclick="alert(this.value)"> //扩展这个函数的作用域方式如下段代码,效果相同可以不加this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="Click Me" onclick="alert(value)">
</body>
<script>
function(){
with(document){
with(this){
}
}
}
</script>
</html>
如果当前元素是表单输入元素,则作用域中还会包含访问表单元素(父元素)的入口,这个函数就变成了如下所示
function(){
with(document){
with(this.form){
with(this){
}
}
}
}
这种扩展方式,事件处理程序无需引用表单元素就能访问其他表单的字段:
<form method="post">
<input type="text" name="username" value="">
<input type="button" value="Echo Username" onclick="alert(username.value)">
</form>
在HTML中指定事件处理程序有3个缺点:
- 时差问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<script>
function showMessage(){
alert("Hello world!");
}
</script>
<body>
<input type="button" value="click me" onclick="showMessage()">
</body>
<script>
</script>
</html>
如上述代码所示:若showMessage()函数是在按钮下方、页面最底部定义的。如果用户在页面解析showMessage()函数之前就单击了按钮,就会引发错误。因此,很多HTML事件处理程序都会被封装到一个try-catch块中。
<input type="button" value="click me" onclick="try{showMessage();}catch(ex){}">
这样即使在showMessage()函数有定义之前单击了按钮,用户将不会看到javascript错误,因为在浏览器有机会处理错误之前,错误就被捕获了。
- 扩展事件处理程序的作用域链在不同浏览器会导致不同结果。不同JavaScript引擎遵循的标示符解析规则略有差异,很可能在访问非限定对象成员时出错。
- HTML与JavaScript代码紧密耦合。如果要更换事件处理程序,就要改动两个地方:HTML代码和JavaScript代码
4.删除通过DOM0级指定的事件处理程序:删除后按钮将不会有任何动作发生
btn.onclick = null
也可以以同样方式删除HTML指定事件处理程序。 5.DOM2级事件处理程序定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener(). DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。如下代码:两个事件处理程序会按照添加它们的顺序触发。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="click me" id="myBtn">
</body>
<script>
var btn = document.getElementById("myBtn");
btn.addEventListener("click",function(){
alert("aaa")
},false); //false表示在冒泡阶段调用事件处理程序,true表示在捕获阶段调用事件处理程序
btn.addEventListener("click",function(){
alert("Hello world");
},false);
</script>
</html>
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;传入的参数和添加处理程序的参数相同。这也就意味着addEventListener()添加的匿名函数将无法移除。
btn.removeEventListener("click",function(){ //无效,无法移除
alert("Hello world");
},false);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="click me" id="myBtn">
</body>
<script>
var btn = document.getElementById("myBtn");
var handler = function(){
alert(this.id);
}
btn.addEventListener("click",handler,false); //重写后可以说明使用的是相同的函数,此时可以移除事件
btn.removeEventListener("click",handler,false);
</script>
</html>
大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度的兼容各种浏览器。最好只在需要在事件到达目标之前截获它的时候将事件处理程序添加到捕获阶段。如果不是特别需要,不建议在事件捕获阶段注册事件处理程序。
6.IE事件处理程序:实现了与DOM类似的方法:attachEvent()和detachEvent()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="click me" id="myBtn">
</body>
<script>
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
alert(this === window); //输出true
},false);
</script>
</html>
IE中使用attachEvent()与DOM0级方法的主要区别在于事件处理程序的作用域。DOM0级中,事件处理程序在其所属元素的作用域内运行;IE中,则是在全局作用域中运行,因此this等于window。
在添加多个事件处理程序时,与DOM方法不同的是,触发顺序相反,但在移除事件处理程序时类似。