处理事件的四种方式:
一.HTML事件处理程序
<input type="button" onclick="showMessage()">
缺点:
1.用户触发事件时,有可能并没有加载完成,会报错(例如上面的showMessage()函数如果在后面才加载到)
解决方法是用try,catch封装好,就不会报错
<input type="button" onclick="try{showMessage();}catch(ex){}">
2.不同浏览器对这种方式的解析略有差异
3.HTML和JavaScript耦合,如果修改要同时改两个地方
二.DOM0级事件处理程序(在冒泡阶段处理)
document.getElementById('btn').onclick=function(){
alert(1);
}
缺点:
1.在执行到这段代码前,点击btn是无反应的。
2.只能添加一个事件
删除DOM0级事件的方法:
三.DOM2级事件处理程序(自定义冒泡还是捕获阶段处理)(IE9及以上和现代的浏览器都支持)
document.getElementById('btn').addEventListener("click",function(){
alert(this);
},false)
注意是click而不是onclick,只有DOM2级和其他的不同,第三个参数默认是false,冒泡
this指向当前的元素
如果同一按钮绑定多个事件,如下,会按照代码顺序执行,先弹出1,再弹出2
document.getElementById('btn').addEventListener("click",function(){
alert(1);
},false)
document.getElementById('btn').addEventListener("click",function(){
alert(2);
},false)
删除DOM2级事件的方法:removeEventListener()
要与addEventListener()时的参数一致,并且如果绑定的是匿名函数,是无法解除绑定的,因为绑定与解绑的匿名函数是两个函数。
四.IE事件处理程序(只有冒泡,没有捕获)(IE8及以下)
document.getElementById('btn').attachEvent("onclick",function(){
alert(this);
})
这里是onclick
this指向window
如果同一按钮绑定多个事件,如下,会按照相反的顺序执行,先弹出2,再弹出1
document.getElementById('btn').attachEvent("onclick",function(){
alert(1);
})
document.getElementById('btn').attachEvent("onclick",function(){
alert(2);
})
删除IE事件的方法:detachEvent()
要与attachEvent()时的参数一致,并且如果绑定的是匿名函数,是无法解除绑定的,因为绑定与解绑的匿名函数是两个函数。
两种事件对象:
1.常见DOM事件对象:
event.type 事件类型
event.eventPhase 事件所处阶段,1表示捕获2表示目标3表示冒泡
event.currentTarget 当前处理的元素,永远等于this
event.target 最终想要处理的目标
event.preventDefault() 取消默认行为(前提是cancelable属性为true)
event.stopPropagation() 停止事件传播(前提是bubbles属性为true)
event.stopImmediatePropagation() 停止事件传播,且自身绑定的后续事件也不再执行
2.IE事件对象:(当使用DOM0级处理时,匿名函数不能传参数event,而要在里面使用window.event)
event.type 事件类型
event.srcElement 最终想要处理的目标
event.returnValue 默认值true,改为false就取消默认行为
event.cancelBubble 默认值false,改为true就取消事件冒泡
事件委托:
为什么要委托:
1.每个函数都是一个对象,占用内存
2.每次绑定事件都访问DOM,访问DOM是十分耗时的
3.如果不委托,元素呈现,有时候还没有添加事件
DOM2级委托:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<ul id="myLinks">
<li id="doSomething">11111</li>
<li id="goSomewhere">22222</li>
<li id="sayHi">33333</li>
</ul>
<script>
var list = document.getElementById("myLinks");
list.addEventListener("click",function(event){
switch(event.target.id){
case "doSomething":
alert(1);
break;
case "goSomewhere":
alert(2);
break;
case "sayHi":
alert(3);
break;
}
},false);
</script>
</body>
</html>
IE委托:
list.attachEvent("onclick",function(event){
switch(event.srcElement.id){
//...
}
});
其他:
在移除带有事件的元素之前,记得要删除对应的事件,不然内存会一直保留(可以在页面卸载前调用onunload事件)
删除事件的另一个用途是阻止冒泡
一般把目标阶段看做冒泡阶段的一部分
一般都在冒泡中处理事件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
div
{
background-color: coral;
border: 1px solid;
padding: 50px;
}
</style>
</head>
<body>
<p>该实例演示了在添加事件监听时冒泡与捕获阶段的不同。</p>
<div id="myDiv">
<p id="myP">点击该段落, 我是冒泡</p>
</div><br>
<div id="myDiv2">
<p id="myP2">点击该段落, 我是捕获</p>
</div>
<script>
document.getElementById("myP").addEventListener("click", function() {
alert("你点击了 P 元素!");
}); //任意true或false,因为冒泡还是捕获在这里效果都一样
document.getElementById("myDiv").addEventListener("click", function(){
alert("你点击了 DIV 元素!");
},false); //先执行里面的p,然后再冒泡到外层DIV
document.getElementById("myP2").addEventListener("click", function() {
alert("你点击了 P2 元素!");
}); //任意true或false,因为冒泡还是捕获在这里效果都是一样
document.getElementById("myDiv2").addEventListener("click", function() {
alert("你点击了 DIV2 元素!");
}, true);//立刻捕获外层DIV,然后再执行里面的P
//true表示立刻执行,false则延迟
</script>
</body>
</html>