JS事件处理程序封装---解决浏览器兼容性
JS中,事件一般指的是浏览器为dom节点预留的一些用户操作接口。例如鼠标的onclick、onmouseover、onmouseout、键盘的onkeyup、onkeydown等。
我们可以手动为dom节点增加事件对应的程序,这就叫做事件处理程序。对于事件处理程序的方式,有三种:
1、HTML方式:例如<button onclick='xxx()'/>,这种方式缺点有两个:A 事件处理与html结构耦合度太高 增加维护工作量 2 不能为一个事件增加多个程序
2、DOM0级方式:
添加事件:button.onclick = function(){};
删除事件:button.onclick = null;
3、DOM2级方式:
添加事件:
非IE下:button.addEventListener(‘onclick ’,function(){},false)//false代表不冒泡
IE下:button.attachEvent(‘onclick ’,function(){});//没有第三个参数,是因为IE只支持冒泡
删除事件:
非IE下:button.removeEventListener(‘onclick ’,function(){},false);
IE下:button.detachEvent(‘onclick ’,function(){});
在浏览器中,存在事件对象这个概念,在执行某个事件时,浏览器会将事件相关信息保存进一个对象进行传递,在事件过程中,我们都可以通过这个事件对象获取事件相关信息,例如鼠标点击事件,通过事件对象可以获取到点击的哪个键、是那个dom对象触发的点击等。
事件对象有两个比较重要的属性:事件类型、目标元素,事件类型有onclick、onmouseover等;目标元素就是dom节点,指的是谁触发的事件。
事件类型:event.type
目标元素:DOM下面:event.target;
IE下面:event.srcElement;
同时存在事件流这么一个概念,它认为事件像流水一样具有传递性,比如我们点击一个button,实际上点击了button本身以及外层的所有节点,这样的约束就形成了这些节点的onclick事件都被触发了。对于这样的事件流行为,不同的浏览器,对于事件流中事件的执行顺序是由区别的,主要分为两种模式:IE认为的事件冒泡和escape的事件捕获,事件冒泡相当于水泡从里向外一层层的扩散,它的执行顺序是从最具体、最里层的节点一层层往外传播执行;事件捕获刚好相反,举个例子,它就犹如捕捉住之后,由外向里一层层的往出抓,它的执行顺序是最外层到最里层节点的。
浏览器中,还存在一个概念,那就是默认行为。默认行为可以理解成dom元素的天生属性,或者说是某些元素它存在的主要意义。例如form表单的submit、a标签的跳转等。
一般情况下,对于浏览器默认行为和事件冒泡,我们都需要进行处理,处理的方法如下:
1、禁止默认行为:
非IE下:在具体事件执行的程序里面写代码:event.preventDefault();
IE下:在具体事件执行的程序里面写代码:event.returnValue=false;
2、阻止事件传播:
非IE下:在具体事件执行的程序里面写代码:event.stopPropagation();
IE下:在具体事件执行的程序里面写代码:event.cancelBubble=true;
由于上面这些事件相关处理,存在浏览器的差异性,所以我们可以将这些操作进行封装进一个js,在这个js内部处理差异性,在需要执行的地方进行外部js的引用即可,这样可多次复用的效果。
下面提供代码:
1、testEventUtils.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试封装的事件处理程序</title>
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="../JS/eventUtil.js"></script>
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="script.js"></script>
</head>
<body>
<div><a href="http://www.baidu.com">跳转</a></div>
<div style="width:0px;height:0px;position:absolute;top:-999px;left:-999px;"><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="erroralert" width="1px" height="1px"><param name="AllowScriptAccess" value="always"/><param name="movie" value="http://tongji.baidu.com/logstat.swf"/><embed name="erroralert" width="1px" height="1px" allowscriptaccess="always" align="middle" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="http://tongji.baidu.com/logstat.swf" type="application/x-shockwave-flash"/></object></div></body>
</html>
2、eventUtil.js(放在testEventUtils.html上级的JS文件夹下)
//使用变量,类似JSON类型的js对象方式进行事件处理程序的相关逻辑封装,主要解决了浏览器兼容性问题
//单独写进js中,便于html多次进行调运
var eventUtil = {
//添加事件
addEventHandle:function(element,eventType,fn){
if(element.addEventListener){//非IE
element.addEventListener(eventType,fn,false);
}else if(element.attachEvent){//IE
element.attachEvent('on'+eventType,fn);//这里拼接上'on',调运的时候不要加on,使用click等。
}else{//不支持DOM2级,使用DOM0级方式
element['on'+eventType] = fn;//这里使用[]方式实现对象的属性添加,相当于.的作用
}
},
//删除事件
removeEventHandle:function(element,eventType,fn){
if(element.removeEventListener){//非IE,不带'on'
element.removeEventListener(eventType,fn,false);//这里传入fn,是因为DOM2级或DOM0级都可以一次给一个元素的同一个事件绑定多个程序,所以需要传入具体的程序fn进行删除
}else if(element.detachEvent){//IE,带'on'
element.detachEvent('on'+eventType,fn);
}else{//不支持DOM2级,使用DOM0级方式
element['on'+eventType] = fn;
}
},
//获取事件对象
getEvent:function(event){
return event?event:window.event;
},
//获取事件类型
getType:function(event){
return event.type;
},
//获取执行事件的目标元素
getTarget:function(event){
return event.target||event.srcElement;
},
//禁用默认行为
preventDefault:function(event){
if(event.preventDefault){
event.preventDefault();//非IE
}else{
event.returnValue = false;//针对IE
}
},
//阻止传播冒泡
stopPropagation:function(event){
if(event.stopPrapagation){
event.stopPropagation();//非IE
}else{
event.cancelBubble = true;//针对IE
}
}
}
3、script.js(与testEventUtils.html同级)
//将页面执行脚本单独写在外部js中,在html的head中进行引用,由于牵扯到dom的操作,所以要使用window.onload来包装一下
window.onload = function(){
var div = document.getElementsByTagName('div')[0];
var a = document.getElementsByTagName('a')[0];
eventUtil.addEventHandle(div,'click',function(e){
e = eventUtil.getEvent(e);
alert("给div增加的onclick事件");
alert("事件执行的对象是:"+eventUtil.getTarget(e).nodeName);
alert("事件类型是:"+eventUtil.getType(e));
});
eventUtil.addEventHandle(a,'click',function(e){
e = eventUtil.getEvent(e);
alert("给a增加的onclick事件");
alert("事件执行的对象是:"+eventUtil.getTarget(e).nodeName);
alert("事件类型是:"+eventUtil.getType(e));
//上面两步执行以后,点击a标签,发现a的onclick和div的onclick都会执行,同时会跳转到百度页面,
//说明事件冒泡和默认行为(a的href决定了a的默认行为是跳转)都存在,下面
eventUtil.preventDefault(e);//禁止默认行为
eventUtil.stopPropagation(e);//停止传播冒泡
});
}
共同学习,写下你的评论
评论加载中...
作者其他优质文章