JS-事件对象
-
事件对象简介
事件对象
—当事件响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递给响应函数;
—在事件对象中封装了当前事件的一切信息,比如鼠标坐标、键盘哪个按键被按下、鼠标滚轮滚动方向等;
—具体可以查看事件对象中相关属性,比如鼠标/键盘相关属性,例如
button
属性,返回事件被触发时,哪个鼠标按钮被点击;—在IE8中,响应函数被触发时,浏览器不会传递事件对象这个参数,在IE8及以下的浏览器中,将事件对象作为
window
对象的属性保存的;因此为了兼容IE8浏览器,可以通过window.event
访问事件对象;—
onmousemove
事件,该事件将会在鼠标在元素移动时触发事件;<script> window.onload = function(){ //实现鼠标在areaDiv移动时,在showMsg显示鼠标坐标 var areaDiv = document.getElementById("areaDiv"); var showMsg = document.getElementById("showMsg"); areaDiv.onmousemove = function(event){ //为了解决事件对象兼容性问题,可以增加一个判断 event = event || window.event; //事件对象的相关属性: //——clientX:可以获取鼠标指针的水平坐标 //——clientY:可以获取鼠标指针的垂直坐标 var x = event.clientX; var y = event.clientY; showMsg.innerHTML = "x="+x+",y="+y; }; }; </script>
—
clientX
和clientY
是用于获取鼠标在当前可见窗口的坐标,其偏移是相对于可见窗口;绝对定位的偏移量是相对于整个页面的;—
pageX
和pageY
可以获取鼠标相对于当前页面的坐标;但是两个属性在IE8中不兼容;所以如果需要兼容IE8,不能使用这两个属性;—为了兼容浏览器,我们可以使用
clientX
和clientY
,可以将此时div
的偏移量设置为滚动条滚动距离+事件对象的偏移量,这样就实现了事件对象和div
重合;—chrome浏览器认为滚动条是
body
的,可以通过body.scrollTop
获取;—火狐等浏览器认为浏览器的滚动条是
html
的;<script> window.onload = function(){ var box1 = document.getELementById("box1"); document.onmousemove = function(event){ event = event || window.event; //为了解决兼容性问题,获取滚动条距离 var st = document.body.scrollTop || document.documentElement.scrollTop; var sl = document.body.scrollLeft || document.documentElement.scrollLeft; }; var left = event.clientX; var top = event.clientY; //设置div的偏移量 box1.style.top = top + st +"px"; box1.style.left = left + sl +"px"; }; </script>
-
事件的冒泡
事件的冒泡(Bubble)
—所谓的冒泡指的是事件的向上传导,当后代元素上的事件被触发,其祖先元素的相同事件也会被触发;
—在开发中,冒泡是十分有用的;
—如果不希望事件冒泡,可以通过事件对象来取消冒泡;可以将事件对象的
cancelBubble
属性设置为true
即可取消冒泡:var event.cancelBubble = true;
-
事件的委派
<script> //事件冒泡举例—事件的委派 var btn = document.getElementById("btn"); btn.onclick = function(){ //创建li var li = document.createElement("li"); var u1 = document.getElementById("u1"); li.innerHTML = "<a class = 'link' href='javascript:;'>新建超链接</a>"; u1.appendChild(li); }; //这里为现有的每一个超链接绑定一个单击响应函数,循环遍历比较麻烦,并且只能为已有的超链接添加单击响应函数,而新添加的超链接必须重新绑定,比较麻烦; //我们希望只绑定一次事件,即可应用到多个元素上,即使元素是后添加的; //我们可以尝试将其绑定给元素的共同的祖先元素; u1.onclick = function(event){ event = event || window.event; if(event.target.className == "link"){ alert("我是超链接"); } }; </script>
事件的委派
—将事件统一绑定给元素共同的祖先元素,这样当后代元素被触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件;
—事件的委派是利用了冒泡,通过事件的委派可以减少事件绑定的次数,提高程序的性能;
—另外,我们可以进行判断,如果触发事件的对象是我们期望的元素,则执行否则不执行;这里需要事件对象,可以通过
target
属性,返回触发事件的对象; -
事件的绑定
—使用
对象.事件 = 函数
的形式绑定响应函数,只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定多个,则后边的会覆盖掉前边的响应函数;—可以通过
addEventListener()
方法为元素绑定响应函数,需要参数:-
事件的字符串,不要
on
,比如onclick
写作"click"
; -
回调函数,当事件触发时,函数会被调用;
-
是否在捕获阶段触发事件,需要一个布尔值,一般都传递
false
;
—使用该种方式可以同时为一个元素的相同事件绑定多个响应函数,这样当事件被触发时,响应函数会按照函数的绑定顺序执行;
—该方法中
this
指向的是绑定事件的对象;—这个方法在Ie8及以下的浏览器不支持;
—
attachEvent()
方法可以在IE8中支持,需要参数:-
事件的字符串,需要
on
; -
回调函数
—这个方法可以同时为一个元素的相同事件绑定多个响应函数,不同的是当事件被触发时,响应函数是后绑定的先执行,执行顺序和
addEventListener
相反;—该方法的
this
指向的是window
;<script> //定义函数,解决兼容性问题 //参数: //1.obj:要绑定事件的对象 //2.eventStr:事件的字符串 //3.callback:回调函数 function bind(obj,eventStr,callback){ if(obj.addEventListener){ obj.addEventListener(eventStr,callback,false); }else{ //可以通过callback.call(obj)修改this的值为绑定事件的对象; //回调函数不传递callback,传递一个匿名函数,在匿名函数调用回调函数; //在匿名函数中调用的回调函数修改this的指定对象; obj.attachEvent("on"+eventStr,function(){ callback.call(obj); }); } } </script>
-
-
事件的传播
—关于事件的传播,网警公司和微软公司有不同的理解;
—微软公司,认为事件应该由内向外传播的,当事件触发时,应该先触发当前元素上的事件然后在向当前元素的祖先元素传播;事件应该在冒泡阶段执行;(事件的冒泡)
—网警公司,认为事件应该是由外向内传播的,当事件触发时,应该先触发当前元素的最外层的祖先元素事件,然后在向内传播给后代元素(事件的捕获阶段)
—W3C综合了两个公司的方案,将事件的传播分为三个阶段(适用于IE9及以上的浏览器):
- 捕获阶段:
—在捕获阶段时,由最外层的祖先元素向目标元素进行事件捕获;但是默认此时不会触发事件;
- 目标阶段
—事件捕获到目标元素,捕获阶段结束,开始在目标元素上触发执行事件;
- 冒泡阶段
—事件从目标元素向其祖先元素传递,依次触发祖先元素上的事件;
—如果希望在捕获阶段就触发执行事件,可以在
addEventListener()
的第三个参数中改为true
;一般情况不会再捕获阶段触发执行事件;—IE8及以下的浏览器无捕获阶段;
-
滚轮事件
—
onmousewheel
为鼠标滚轮滚动事件;—在火狐中使用
DOMMouseScroll
实现滚轮事件,该事件需要通过addEventListener()
函数实现;—
event.wheelDelta
可以获取鼠标滚轮方向,向上滚动是正值,向下滚动是负值;—
wheelDelta
属性在火狐中不支持,火狐中使用event.detail
,向上滚动为负值,向下滚动为正值;—当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动;这是浏览器的默认行为,如果不希望发生,则可以取消这个默认行为;
—注意,使用
addEventListener()
方法绑定响应函数时,取消浏览器默认行为时,不能使用return false
;需要使用event
取消默认行为:event.preventDefault();
但是IE8不支持该方法,如果直接调用会报错;所以使用时需要判断:event.preventDefault && event.preventDefault();
-
键盘事件
onkeydown
事件:—按键被按下;
—对于
onkeydown
来说,当某个按键一直按下,它会连续触发事件;—当
onkeydown
连续触发时,第一次和第二次之间触发响应间隔会相对较长,其他的会非常快;—这种设计是为了防止错误操作;
onkeyup
事件—按键被松开;
—键盘事件一般都绑定给可以获取焦点的对象(表单对象)或者是
document
对象;—可以通过
event.keyCode
来获取按键编码;(已弃用,使用key
);—通过它可以判断哪个按键被按下;
—
altKey
:返回事件被触发时,ALT键是否被按下;—
ctrlKey
:返回事件被触发时,Ctrl键是否被按下;—
shiftKey
:返回事件被触发时,Shift键是否被按下;以上按键如果按下,则返回
true
,否则返回false
;—在表单对象中文本框中输入内容属于
onkeydown
的默认行为,如果onkeydown
通过return false
取消了默认行为,则输入的内容不会出现在文本框中;<script> //拖拽函数 //需要传递一个参数,即需要开启拖拽的元素 function drag(obj){ //为对象绑定鼠标按下事件 obj.onmousedown = function(event){ //解决IE8浏览器兼容问题,设置捕获 //setCapture()方法只有IE支持,但是在火狐中调用不会报错; //但是在chrome中使用会报错,因此可以加一个判断 obj.setCapture && obj.setCapture(); event = event || window.event; //为了使得鼠标按下时就固定在按下的位置,需要计算偏移量 //求出obj水平偏移量:鼠标.clientX - 元素.offsetLeft var ol = event.clientX - obj.offsetLeft; //求出obj垂直偏移量:鼠标.clientY - 元素.offsetTop var ot = event.clientY - obj.offsetTop; //绑定鼠标移动事件,这里绑定给document document.onmousemove = function(event){ event = event || window.event; //获取鼠标坐标 var x = event.clientX - ol; var y = event.clientY - ot; //修改被拖拽元素的位置 obj.style.left = x + "px"; obj.style.top = y +"px"; }; //为obj绑定时,当鼠标移动到其他对象区域时,触发事件无效,因此要为document绑定 document.onmouseup = function(){ //当鼠标松开时,被拖拽元素固定在当前位置 //取消document的onmousemove事件 document.onmousemove = null; //需要取消onmouseup事件,相当于只会响应一次,一次性事件; document.onmouseup = null; //当调用一个元素的setCapture()方法以后,这个元素会把下一次所有鼠标按下的相关事件捕获的自身身上; //当鼠标松开时,取消obj的捕获 obj.releaseCapture && obj.releaseCapture(); }; //当我们去拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容此时会导致拖拽功能异常; //这个是浏览器提供的默认行为,如果不希望发生这个行为,可以通过return false取消这个行为,但是IE8浏览器不起作用; //在IE8浏览器中可以使用setCapture()方法进行事件捕获; return false; }; } </script>