事件
事件,就是用户与浏览器之间的交互行为。比如点击按钮、鼠标移动、关闭窗口等。
我们可以为按钮对应的事件绑定处理函数,这样当事件被触发时,其对应的函数就会被调用。
事件对象
当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数。在事件对象中封装了当前事件相关的一切信息,比如:鼠标坐标、键盘在哪个按键按下等。
在IE8及以下浏览器中,是将事件对象作为window对象的属性保存的,所以我们需要考虑兼容性的问题:
可以使用
event = event || window.event
例子:
元素.事件 = function(event){
event = event || window.event;
};
事件冒泡
事件冒泡指的是事件向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发。如果不希望发生事件冒泡可以通过对象事件来取消。
取消冒泡:将事件对象的cancelBubble属性设置为true,即可取消冒泡。
例子:
<body>
<div id="father">
<div id="son"></div>
</div>
<script type="text/javascript">
var father = document.getElementById("father")
var son = document.getElementById("son")
father.onclick = function(){
alert("我是爸爸")
}
son.onclick = function(){
alert("我是儿子")
}
</script>
</body>
为了使页面简洁,以上代码省略了样式表,当点击id为son的元素后,出现结果如下:
我们可以看到父元素的点击函数也执行了,这就是冒泡。
事件委派
事件委派指的是将事件统一绑定给元素的共同祖先,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。
事件委派是利用了冒泡,该方法可以减少事件绑定的次数,提高程序性能。
事件绑定
在学习事件绑定之前,我们绑定事件函数是通过对象.事件 = 函数的形式来绑定的。
该方法只能为一个元素的一个对象绑定一个响应函数而不能同时绑定多个,否则后边的函数会覆盖掉前边的函数。
addEventListener():为元素绑定响应函数
参数:
第一个:事件的字符串(带"on"的省略“on”)
第二个:回调函数,当事件触发时该函数会被调用
第三个:是否在捕获阶段触发事件,需要一个布尔值,一般传false(具体下面会提到)
该方法可以同时为一个元素的相同事件同时绑定多个响应函数,这样当事件被触发时,响应函数将会按照绑定顺序执行。
注:该方法不支持IE8及以下浏览器
兼容方法:使用attachEvent()来绑定事件
参数:
第一个:事件的字符串(带"on"的不能省略"on")
第二个:回调函数
该方法也可以同时为一个元素的相同事件同时绑定多个响应函数,但是执行顺序是后绑定先执行。
为了在程序中解决该问题,我们需要定义一个函数:
function 自定义函数名(obj , eventStr , callback){
if(obj.addEventListener){
//大部分浏览器兼容的方式
obj.addEventListener(eventStr , callback , false);
}else{
/*
* this是谁由调用方式决定
* callback.call(obj)
*/
//IE8及以下
obj.attachEvent("on"+eventStr , function(){
//在匿名函数中调用回调函数
callback.call(obj);
});
//上面obj指对象,evenStr指事件(不带“on”),callback指回调函数
事件的传播
W3C将事件传播分成了三个阶段:
- 捕获阶段:在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不触发事件
- 目标阶段:事件捕获到目标元素,捕获开始在目标元素上触发事件
- 冒泡阶段:事件从目标元素向它的祖先元素传递,依次触发祖先元素上的事件如果希望在捕获阶段就触发事件,可以将上面addEventListener()的第三个参数设置为true。
注:IE8及以下的浏览器没有捕获阶段。
下面是基于上述知识的一道拖拽练习:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#box1{
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
#box2{
width: 100px;
height: 100px;
background-color: yellow;
position: absolute;
left: 200px;
top: 200px;
}
</style>
<script type="text/javascript">
window.onload = function(){
/*
* 拖拽box1元素
* - 拖拽的流程
* 1.当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
* 2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
* 3.当鼠标松开时,被拖拽元素固定在当前位置 onmouseup
*/
//获取box1
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var img1 = document.getElementById("img1");
//开启box1的拖拽
drag(box1);
//开启box2的
drag(box2);
drag(img1);
};
/*
* 提取一个专门用来设置拖拽的函数
* 参数:开启拖拽的元素
*/
function drag(obj){
//当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
obj.onmousedown = function(event){
//设置box1捕获所有鼠标按下的事件
/*
* setCapture()
* - 只有IE支持,但是在火狐中调用时不会报错,
* 而如果使用chrome调用,会报错
*/
/*if(box1.setCapture){
box1.setCapture();
}*/
obj.setCapture && obj.setCapture();
event = event || window.event;
//div的偏移量 鼠标.clentX - 元素.offsetLeft
//div的偏移量 鼠标.clentY - 元素.offsetTop
var ol = event.clientX - obj.offsetLeft;
var ot = event.clientY - obj.offsetTop;
//为document绑定一个onmousemove事件
document.onmousemove = function(event){
event = event || window.event;
//当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
//获取鼠标的坐标
var left = event.clientX - ol;
var top = event.clientY - ot;
//修改box1的位置
obj.style.left = left+"px";
obj.style.top = top+"px";
};
//为document绑定一个鼠标松开事件
document.onmouseup = function(){
//当鼠标松开时,被拖拽元素固定在当前位置 onmouseup
//取消document的onmousemove事件
document.onmousemove = null;
//取消document的onmouseup事件
document.onmouseup = null;
//当鼠标松开时,取消对事件的捕获
obj.releaseCapture && obj.releaseCapture();
};
/*
* 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
* 此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
* 如果不希望发生这个行为,则可以通过return false来取消默认行为
*
* 但是这招对IE8不起作用
*/
return false;
};
}
</script>
</head>
<body>
我是一段文字
<div id="box1"></div>
<div id="box2"></div>
<img src="img/an.jpg" id="img1" style="position: absolute;"/>
</body>
</html>