1.事件简介
(1)定义
指的是文档或者浏览器窗口中发生的一些特定交互瞬间。我们可以通过侦听器(或者处理程序)来预定事件,以便事件发生的时候执行相应的代码。
事件类型(event type):事件类型是一个用来说明发生什么类型事件的字符串。像鼠标悬浮,按下键盘等。我们也可以把事件类型叫做事件名字,用特定的名字来标识所谈论的特定类型的事件。
事件目标(event target):事件目标是发生的事件或与之相关的对象。当讲事件时,我们必须同时指定类型和目标。像window上的load事件或者链接的click事件。在客户端js的应用程序中,Window、Document、和Element对象是最常见的事件目标,但是某些事件也是由其它类型的对象触发的。
事件对象(event object):事件对象是与特定事件相关且包含有关该事件详细信息的对象。事件对象作为参数传递给事件处理程序函数。所有的事件对象都有用来指定事件类型的type属性和指定事件目标的target属性。每个事件类型都为其相关的事件对象定义一组属性。
事件传播(event propagation):事件传播是浏览器决定那个对象触发其事件处理程序的过程。
(2)事件模型
内联模型:在HTML中把事件处理函数作为属性执行js代码,这种模型是最传统接单的一种处理事件的方法。在内联模型中,事件处理函数是HTML标签的一个属性,用于处理指定事件。虽然内联在早期使用较多,但它是和HTML混写的,并没有与HTML分离。例如:
<input type="button" value="btn1" onclick="alert('hello world');">
<input type="button" value="btn2" onclick="test()">
<script>
function test() {
alert("hello world2");
}
</script>
脚本模型:由于内联模型违反了HTML与JavaScript代码层次分离的原则。为了解决这个问题,我们可以在JavaScript中处理事件,这种处理方式就是脚本模型,例如:
<input type="button" value="btn3" id = "btn3">
<script>
var btn = document.getElementById("btn3");
btn.onclick = function () {
alert("btn3 clicked");
}
但是这种处理方式无法对一个事件添加多个处理函数。
DOM2模型:“DOM2级事件”定义了两个方法,用于添加事件和删除事件处理程序的操作:
addEventListener()和removeEventListener()。所有DOM节点中都包含这两
个方法,并且它们都接受3个参数;事件名、函数、冒泡或捕获的布尔值(true
表示捕获,false表示冒泡)。
在IE11之前中实现了DOM中类似的两个方法:attachEvent()和detachEvent().这两个方法接受相关的两个参数:事件处理程序名称和事件处理程序函数。IE11之前版本中只支持事件冒泡,所以通过attachEvent()添加的事件处理都会被添加到冒泡阶段,不过IE11已经不再任性了,开始与标准接轨了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="box1" style="background:#ff6600; width: 300px; height: 300px;">
<input type="button" value="btn1" id = "btn1">
</div>
<script>
var box1 = document.getElementById("box1");
var btn1 = document.getElementById("btn1");
btn1.addEventListener('click', function (e) {
alert("btn1 clicked");
var e = e || window.event;
if(typeof e.cancelBubble == 'undefined')
{
e.stopPropagation();
}else {
e.cancelBubble = true;
}
}, false);
box1.addEventListener('click', function () {
alert("box1 clicked");
}, false);
document.body.addEventListener('click', function () {
alert("bocy clicked");
}, false);
document.documentElement.addEventListener('click', function () {
alert("html clicked");
}, false);
document.addEventListener('click',function () {
alert("document clicked");
}, false);
//button -> div ->body ->html ->document
</script>
</body>
</html>
我们可以为一个事件添加多个处理函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="test1" id = "btn1">
<script>
var btn1 = document.getElementById("btn1");
btn1.addEventListener("click", function () {
alert("a");
}, false);
var handler = function () {
alert("b");
}
btn1.addEventListener("click", handler, false);
btn1.addEventListener("click", function () {
alert("c");
}, false);
</script>
</body>
</html>
(3)传统事件类型
事件对象Event
常量:
属性:
方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="EventUtil.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<input type="button" value="test1" id = "btn1" />
<script>
var btn1 = document.getElementById("btn1");
var handler = function (e) {
console.log(this); //input
console.log(e.currentTarget); //input
console.log(e.target); //input
}
EventUtil.addHandler(btn1, 'click', handler);
EventUtil.addHandler(document.body, 'click', function (e) {
console.log(this); //body
console.log(e.currentTarget); //body
console.log(e.target); //input
})
</script>
</body>
</html>
鼠标事件
<script>
var btn1 = document.getElementById("btn1");
var handler = function (e) {
switch (e.type) {
case 'click':
alert("clicked");
break;
case 'mouseover':
event.target.style.backgroundColor = "red";
break;
case "mouseout":
event.target.style.backgroundColor = '';
}
};
btn1.onclick = handler;
btn1.onmouseover = handler;
btn1.onmouseout = handler;
</script>
框架/对象(Frame/Object)事件
键盘事件
目标事件对象
表单事件
剪贴板事件
打印事件
拖动事件
动画事件
过渡事件
其它事件
事件监听对象
文档事件对象
鼠标/键盘事件对象
属性:
方法:
注意:
所有的事件处理函数都会都有两个部分组成,on + 事件名称,例如click事的事件处理函数就是:onclick。在这里,我们主要谈论脚本模型的方式来构建事件,违反分离原则的内联模式,我们忽略掉。
对于每一个事件,它都有自己的触发范围和方式,如果超出了触发范围和方式,事件处理将失效。
2.事件流
事件流是描述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候,那么你点击其中一个元素,并不是只有当前被点击的元素会触发事件,而层叠在你点击范围的所有元素都会触发事件。事件流包括两种模式:冒泡和捕获。事件冒泡,是从里往外逐个触发。事件捕获,是从外往里逐个触发。那么现代的浏览器默认情况下都是冒泡模型,而捕获模式则是早期的Netscape默认情况。而现在的浏览器要使用DOM2级模型的事件绑定机制才能手动定义事件流模式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="box1" style="background:#ff6600; width: 300px; height: 300px;">
<input type="button" value="btn1" id = "btn1">
</div>
<script>
var box1 = document.getElementById("box1");
var btn1 = document.getElementById("btn1");
box1.onclick = function () {
alert("box1 clicked");
}
btn1.onclick = function (e) {
alert("btn1 clicked");
var e = e || window.event;
//e.stopPropagation(); //取消冒泡
if(typeof e.cancelBubble == "undefined") {
e.stopPropagation();
}else {
e.cancelBubble = true;
}
}
document.body.onclick = function () {
alert("body clicked");
}
document.documentElement.onclick = function () {
alert("html clicked");
}
document.onclick = function () {
alert("document clicked");
}
//button -> div ->body ->html ->document
</script>
</body>
</html>
3.事件兼容
事件绑定:addEventListener与attachEvent
事件移除:removeEventListener与detachEvent
获取事件对象:e.target与 window.event.srcElement
阻止冒泡:e.stopPropagation与window.event.cancelBubble
阻止默认:e.preventDefault与window.event.returnValue