事件对象
事件对象
1.事件对象
事件对象
- 当事件的响应函数被触发的时候,浏览器每次都会将一个事件对象作为实参传递进相应函数
- 在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标\键盘某按键被按下\鼠标滚轮滚动方向等.
鼠标\键盘属性
<练习:鼠标在areaDiv中移动时,在showMsg中来显示鼠标的坐标>
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../../css/reset.css">
<link rel="stylesheet" href="../../css/normalize.css">
<link rel="stylesheet" href="p5.css">
<script defer src="p5.js"></script>
</head>
<body>
<div id="areaDiv"></div>
<div id="showMsg"></div>
</body>
</html>
CSS代码
#areaDiv {
border: 1px solid black;
width: 300px;
height:100px;
margin: 10px auto;
}
#showMsg {
border:1px solid black;
width:300px;
height:20px;
margin:0 auto;
text-align: center;
}
JS代码
var areaDiv = document.getElementById("areaDiv");
var showMsg = document.getElementById("showMsg");
areaDiv.onmousemove = function(event){
/* var x;
var y;
if(event){
x = event.clientX;
y = event.clientY;
}
else{
x = window.event.clientX;
y = window.event.clientY;
} */
//兼容IE8 的写法
event = event || window.event;
var x = event.clientX;
var y = event.clientY;
showMsg.innerHTML = "X = "+ x + ", Y = " + y;
}
效果

<练习2:box跟着鼠标移动>
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../../css/reset.css">
<link rel="stylesheet" href="../../css/normalize.css">
<link rel="stylesheet" href="p6.css">
<script defer src="p6.js"></script>
</head>
<body>
<div class="box1" style="left:0; top:0"></div>
</body>
</html>
CSS代码
.box1{
position: absolute;
height:200px;
width:200px;
background-color: red;
}
javascript代码
var box = document.getElementsByClassName("box1")[0];
box.onmousemove = function(event){
event = event || windows.event;
var left = event.clientX;
var top = event.clientY;
this.style.left = (left - this.clientWidth / 2) + "px";
this.style.top = (top - this.clientHeight / 2) + "px";
}
效果

2.事件的冒泡
所谓事件的冒泡指的是事件的向上传到,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发.
在开发中大部分情况下冒泡都是有用的,如果不希望发生事件的冒泡可以通过事件对象来取消冒泡.
可以将事件对象的cancelBubble设置为true,即可取消冒泡.
<例子1:事件的冒泡>
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../../css/reset.css">
<link rel="stylesheet" href="../../css/normalize.css">
<link rel="stylesheet" href="p7.css">
<script defer src="p7.js"></script>
</head>
<body>
<div id="box1">
我是div
<span id="s1">
我是span
</span>
</div>
</body>
</html>
CSS代码
#box1{
width:200px;
height: 200px;
background-color: brown;
}
#s1{
background-color:darkgoldenrod;
}
JS代码
document.getElementById("s1").onclick = function() {
alert("我是span");
}
document.getElementById("box1").onclick = function() {
alert("我是div");
}
document.body.onclick = function() {
alert("我是body");
}
document.documentElement.onclick = function(){
alert("我是HTML");
}

取消冒泡的JS代码
document.getElementById("s1").onclick = function(event){
// 兼容event
event = event || window.event;
alert("我是span"); // 我是span
event.cancelBubble = true;
};
3.事件的委派(Delegate)
事件的委派指的是将事件统一绑定给元素的共同的祖先元素.这样当后代元素上的事件触发时,会一直冒泡到祖先元素,而通过祖先元素的相应函数来处理事件,
事件的委派利用了冒泡,通过委派来减少事件绑定的次数,提高程序的性能.

首先我们来看一个例题:
HTML代码
<button type="button" id="btn">Add</button>
<ul id="ulDiv">
<li><a href="javascript:;" class="link">超链接1</a></li>
<li><a href="javascript:;" class="link">超链接2</a></li>
<li><a href="javascript:;" class="link">超链接3</a></li>
</ul>
JS代码
function clickFun(){
alert("超链接");
}
window.onload = function(){
// 为每一个超链接都绑定一个单击响应函数
var aList = document.getElementsByTagName("a");
for(var i=0;i<aList.length;i++){
aList[i].onclick = clickFun;
}
var btn = document.getElementById("btn");
var ulDiv = document.getElementById("ulDiv");
btn.onclick = function(){
var li = document.createElement("li");
li.innerHTML = "<a href=\"javascript:;\">add超链接</a>";
ulDiv.appendChild(li);
};
};
虽然我们为每一个超链接都绑定了一个单击响应函数,但是这种操作比较麻烦,只能为已有的超链接设置事件,而新添加的超链接必须重新绑定.如果我们希望只绑定一个事件就可以应用到多个元素上,我们就可以用事件的委派.
ulDiv.onclick = function(){
alert("事件委派超链接");
};
这样虽然单击每个连接都可以触发单击响应函数,但是我们是给整个ul绑定的,在点击ul块内除超链接以外的部分时,也会触发事件,这是我们不想要的,那我们应该怎么做呢?
这个时候我们需要判断一下触发事件的元素是谁,然后再决定执行不执行.
ulDiv.onclick = function(event){
event = event || window.event;
// 如果触发事件的对象是我们期望的元素,则执行,则不执行
// alert(event.target); // 点击超链接外:[object HTMLLIElement]; 点击超链接:javascript:;
if(event.target.className == "link"){
alert("事件委派超链接");
}
};
但是这种写法也存在问题,当一个超链接class不止有link时,就会报错,此时我们可以用target的tagName来代替className.
<li><a href="javascript:;" class="link hello">超链接1</a></li> <!-- 失效 -->
<li><a href="javascript:;" class="link">超链接2</a></li>
<li><a href="javascript:;" class="link">超链接3</a></li>
ulDiv.onclick = function(event){
event = event || window.event;
if(event.target.tagName == "A" || event.target.tagName == "a"){
alert("事件委派超链接");
}
};
4.事件的绑定
使用对象.事件 = 函数的形式绑定相应函数,它只能同时为一个元素的一个事件绑定一个相应函数,如果绑定了多个,后面的会覆盖掉前面的.
var btn = document.getElementById("btn");
// 为btn绑定一个单击响应函数
btn.onclick = function() {
alert(1);
};
// 为btn绑定第二个响应函数
btn.onclick = function() {
alert(2); // 2
};
addEventListener() 和attachEvent()
其中addEventListener()是除IE8及以下浏览器可以使用的,而attachEvent()是IE8及以下浏览器支持的.
addEventListener()的参数
- 事件的字符串,不要on
- 回调函数,当事件触发时该函数会被调用
- 是否在捕获阶段触发事件,需要一个布尔值,一般都传false
attachEvent()的参数 - 事件的字符串,要on
- 回调函数
所以我们需要自己封装一个方法来适应不同的浏览器
// 定义一个函数,用来为指定元素绑定响应函数
// 参数:
// - obj 要绑定事件的对象
// - eventStr 事件的字符串
// - callback 回调函数
function bind(obj, eventStr, callback) {
if (obj.addEventListener) {
obj.addEventListener(eventStr, callback, false);
} else {
obj.attachEvent("on" + eventStr, callback);
}
}
但是目前还存在一个问题,这两个对象this所指向的是不一样的.
bind(btn, "click", function() {
alert(this); // IE8: [object window];非IE8:[object HTMLButtonElement]
});
所以我们可以使用call和apply来对bind函数进行优化
function bind(obj, eventStr, callback) {
if (obj.addEventListener) {
obj.addEventListener(eventStr, callback, false);
} else {
// this是谁由调用方式决定
// callback.call(obj)
obj.attachEvent("on" + eventStr, function(){
// 在匿名函数中调用回调函数
callback.call(obj);
});
}
}
5.事件的传播
事件的传播分为三个阶段
- 捕获阶段:在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件.
- 目标阶段:事件捕获到目标元素,捕获结束后开始在目标元素上触发事件.
- 冒泡阶段:时间从目标元素向他的祖先元素传递,依次触发祖先元素上的事件.
![image]()
如果我们希望在捕获阶段就触发事件,可以在addEventListener()的第三个参数中设置为true,一般情况下我们不希望在捕获阶段就触发事件,所以这个参数一般都是false.
IE8及以下的浏览器没有捕获阶段.
6.拖拽
拖拽的流程
- 当鼠标在被拖拽元素上按下时,开始拖拽
onmousedown. - 当鼠标移动时被拖拽元素跟随鼠标移动
onmousemove. - 当鼠标松开时,被拖拽元素固定在当前位置
onmouseup.
![image]()
setCapture
setCapture可以将鼠标事件锁定在指定的元素上,当元素捕获了鼠标事件后,该事件只能作用在当前元素上。
以下情况会导致事件锁定失败:
- 当窗口失去焦点时,锁定的事件,自动就会取消。
- alert也会导致事件的锁定取消。解决办法是在alert之后再次锁定。
- 鼠标右键也会导致事件解锁。
使用setCapture可以解决IE8及以下浏览器拖拽网页中内容时,浏览器会默认去搜索引擎中搜索内容,此时会导致拖拽功能的异常.其为IE浏览器特有.使用完以后要releaseCapture
我们把拖拽功能封装成一个函数:
// 拖拽方法封装成一个函数
function draw(obj){
obj.onmousedown = function(event) {
obj.setCapture && obj.setCapture();
event = event || window.event;
var boxLeft = event.clientX - obj.offsetLeft;
var boxTop = event.clientY - obj.offsetTop;
document.onmousemove = function(event) {
event = event || window.event;
obj.style.left = event.clientX - boxLeft + "px";
obj.style.top = event.clientY - boxTop + "px";
};
document.onmouseup = function(event) {
document.onmousemove = null;
document.onmouseup = null;
obj.releaseCapture && obj.releaseCapture();
};
return false;
};
}
HTML代码
<div id="box1"></div>
<div id="box2"></div>
<img src="img/an.jpg" id="img" style="width: 320px;height: 320px;position: absolute;left:200px;top:400px;"/>
JS代码调用函数
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var img = document.getElementById("img");
draw(box1);
draw(box2);
draw(img);



浙公网安备 33010602011771号