为了账号安全,请及时绑定邮箱和手机立即绑定

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);//停止传播冒泡
    });
}
点击查看更多内容
18人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消