事件
当浏览器调用事件的响应函数时,每次都会传递一个事件对象作为参数
在事件对象封装了当前事件相关的信息,比如:鼠标的坐标 键盘哪个按键被按下。。。
我们可以通过该对象来获取事件相关的信息
event = event || window.event
- 在IE8及以下的浏览器中,没有将事件对象作为参数传递进函数,所以我们就不能以参数的形式来使用事件对象。
- 在IE8中,是将事件对象作为window对象的属性保存的,需要使用window.event来使用
事件的传播
- 捕获阶段
- 事件从最外层的元素(document),向目标元素进行事件的捕获
- 此阶段默认不会触发事件
- 目标阶段
- 目标指的是触发事件的元素,捕获到目标元素则捕获阶段停止
- 冒泡阶段
- 事件从目标元素向祖先元素中冒泡,此时开始触发事件
- 默认事件都是在冒泡阶段执行的
事件都是默认在冒泡阶段执行的,一般不需要在捕获阶段触发事件
如果希望在捕获阶段执行事件,则需要将addEventListener()的第三个参数修改为true
IE8及以下的浏览器没有捕获阶段,也不能设置在捕获阶段触发事件
捕获和释放事件
当选择多个元素,但是只想拖拽选中中的一个元素就可以给这个元素设定捕获事件,这样事件就只传给这一个元素。
捕获完之后,事件结束时一定要释放。
在chrome中没有setCapture()和releaseCapture()方法
所以调用会导致浏览器报错
捕获事件
box1.setCapture || box1.setCapture();
释放事件
box1.releaseCapture || box1.releaseCapture();
事件冒泡
-
冒泡简单来说就是事件的向上传导,当后代元素上的事件被触发时,将会导致祖先元素上的相同事件也被触发
-
大部分情况下冒泡都是对开发有利的,可以简化我们的开发
-
如果不希望发生事件的冒泡,则可以通过事件对象来取消冒泡
-
将事件对象的cancelBubble属性设置true,即可取消冒泡
event.cancelBubble = true;取消冒泡
事件的委派
-
指统一将多个元素上的事件绑定到他们共同的祖先元素上,
-
这样只需要绑定一次即可同时处理多个元素上的相同的事件,
-
这样简化了代码的开发,也可以确保新添加的元素上也可以有事件响应函数
属性
//获取出发事件的对象
event.target
事件的绑定
使用 对象.事件
的形式不能同时为一个元素的同一个事件绑定多个处理函数
如果绑定了多个,则后边的会将前边的覆盖掉
readFileDom.onclick = function (event) {}
如果需要同时为一个事件绑定多个响应函数,则在正常浏览器中使用addEventListener()
来绑定,响应函数按照绑定的顺序执行,它的响应函数中的this就是绑定事件的对象
参数
-
要绑定的事件(字符串 不要on)
-
回调函数(事件触发时,该函数将会执行)
-
是否在捕获阶段触发事件(都传false)
readFileDom.addEventListener("click", function (event) {},false);
在IE中,使用的是attachEvent()
来绑定的事件,而它的响应函数中的this是window
- 可以同时为一个事件绑定多个响应函数,但是它的执行顺序不一定
-
ie9 ie10 先绑定先执行
-
ie8 后绑定先执行
readFileDom.attachEvent("onclick",function (event) {});
自定义兼容所有浏览器的事件绑定
/*
* 参数:
* obj 要绑定事件的对象
* eventStr 事件的字符串,不要on
* callback 回调函数,事件触发时调用的函数
*/
function bind(obj , eventStr , callback){
if(obj.addEventListener){
//如果是正常浏览器
obj.addEventListener(eventStr , callback , false);
}else{
//IE8
/*
* attachEvent()中的回调函数的this是window,需要修改为obj
* this是谁由函数的调用方式决定
* 1.以函数的形式调用,this是window
* 2.以方法的形式调用,this是调用方法的对象
* 3.以构造函数的形式调用,this是新创建的对象
* 4.使用call和apply调用时,this是第一个参数
*/
obj.attachEvent("on"+eventStr , function(){
/*
*在attchEvent()中不传递callback而是传递一个匿名函数
*这样在事件触发时,浏览器不会调用callback而是调用匿名函数
*在匿名函数中来调用回调函数
*/
callback.call(obj);
});
}
}
取消浏览器的默认行为
* 当我们在浏览器中选中一个文字或一个内容并拖动时,浏览器会自动去搜索引擎中搜索该内容
* 但是这个行为的出现会导致拖拽功能出现异常,这一行为是浏览器的默认行为
* 如果不希望发生该行为,则可以在事件中取消默认行为
方法一
直接在事件的函数中返回false。
`return false;`
方法二
使用addEventListener()绑定的事件,不能通过return false来取消默认行为
需要调用事件对象 preventDefault()方法来取消默认行为
但是在IE8中没有该方法
`event.preventDefault || event.preventDefault();`
鼠标滚轮事件
-
Firefox的滚轮事件使用 DOMMouseScroll
elem.addEventListener(‘DOMMouseScroll’, func, false);
-
其他浏览器的滚轮事件使用 mousewheel
window.onmousewheel=document.onmousewheel=func; //IE/Opera/Chrome
判断滚轮向上或向下,Firefox 使用detail
,其余浏览器使用wheelDelta
;
滚动值的区别
IE 鼠标滚轮向上滚动是120,向下滚动是-120
Opera 鼠标滚轮向上滚动是120,向下滚动是-120
Chrome 鼠标滚轮向上滚动是120,向下滚动是-120
Safari 鼠标滚轮向上滚动是360,向下滚动是-360
Firefox 鼠标滚轮向上滚动是-3,向下滚动是3
兼容写法
//判断鼠标滚轮滚动方向
if (window.addEventListener){//火狐浏览器会识别该方法
window.addEventListener('DOMMouseScroll', wheel, false);
}
window.onmousewheel = document.onmousewheel = wheel;//W3C
//统一处理滚轮滚动事件
function wheel(event){
var delta = 0;
if (!event) event = window.event;
if (event.wheelDelta) {//获取事件对象中wheelDelta的值,这里表示向上滑动
//IE、chrome浏览器使用的是wheelDelta,并且值为“正负120”
delta = event.wheelDelta/120;
if (window.opera) delta = -delta;//因为IE、chrome等向下滚动是负值,FF是正值,为了处理一致性,在此取反处理
} else if (event.detail) {
//火狐浏览器使用的是detail,其值为“正负3”
delta = -event.detail/3;
}
if (delta)
handle(delta);
}
//上下滚动时的具体处理函数
function handle(delta) {
if (delta <0){//向下滚动
}else{//向上滚动
}
}
键盘事件
键盘事件一般都要绑定给可以获取焦点的元素(一般指表单项),或者是document
onkeydown
- 当按下键盘上的一个按键一直不松开时,会连续的触发onkeydown事件,
- 但是第一次触发和第二次触发的间隔会比较长,而第二次以后会一直连续触发
- 这种设计是为了防止误操作
onkeyup
事件属性
keycode
可以用来获取当前按键的编码
altKey
判断是否按下alt键
ctrlKey
判断是否按下ctrl键
shiftKey
判断是否按下shift键
拖拽事件
需要给被拖拽元素设置dragable = "true";否则无法实现拖拽效果
<div class="box" draggable="true"></div>
释放区元素事件
ondragend
进入拖拽区
ondragover
在拖拽区中
在里面添加event.preventDefault();用来阻止默认拖拽样式
ondragleave
离开拖拽区
ondrop
在拖拽区中释放鼠标
监听拖拽外部文件
var fileList = ev.dataTransfer.files; //所有被拖拽的网页外的文件
拖拽元素事件
ondragstart
拖拽开始
在这里可以设置鼠标拖拽样式
even.dataTransfer.dropEffect = "uninitialized";
even.dataTransfer.effectAllowed = "uninitialized";
上述两个属性可设置的值包括,none, copy, copyLink, copyMove(默认),
link, linkMove, move, all 和 uninitialized。
//使用图片设置鼠标样式
even.dataTransfer.setDragImage(imgdom,0,0)
img: 图片的DOM,
xOffset : 水平偏移量
yOffset : 垂直偏移量
ondrag
拖拽中
ondragend
拖拽结束
手机触屏事件
touchstart
touchmove
touchend
手机事件需要使用addeventlistener()
添加事件
bodyDom.addEventListener("touchstart", function (event) {
var touchArr = event.targetTouches;//获取元素上触摸手机的列表
var touch = touchArr[0];
touchArr[0].identifier;返回被触摸对象的唯一标识符。手指在屏幕表面滑动的过程中,触点具有相同标识符,这能让你一直的追踪的相同的触摸事件。
touch.target : 被触摸的DOM元素。
touch.screenX , 返回距离设备屏幕左边缘的X轴坐标
touch.screenY , 返回距离设备屏幕上边缘的Y轴坐标
touch.clientX ,返回距离浏览器视窗左边缘X轴坐标,不包括滚动条( scroll offset )。
touch.clientY ,返回距离浏览器视窗上边缘Y轴坐标,不包括滚动条( scroll offset )。
touch.pageX , 返回距离HTML文档左边缘的的X轴坐标,与Touch.clientX不同,它包括滚动条。
touch.pageY ,返回距离HTML文档左边缘的的Y轴坐标,与Touch.clientY不同,它包括滚动条。
radiusX/radiusY/rotationAngle:画出大约相当于手指形状的椭圆形,分别为椭圆形的两个半径和旋转角度。该属性暂时处于试验阶段。
}, false);
点透
原因
- touchstart 和 click (PC端的事件) 会依次执行,click 会在touchstart执行后 300ms 执行。
- 如果当touchstart 调用了 display: none; 后续的 click 就会点击到 a 链接元素,造成页面跳转
解决方法
- touchstart 中添加
ev.preventDefault();
阻止后续 click 执行。
点透产生的条件:
1.被点击事件设置浮动
2.点击浮层,让浮层 display: none;
3.点击处的下方有 a 连接
4.移动端
网友评论