【兼容封装】addEventListener()和attachEvent()跨浏览器的兼容性处理

本文深入解析了addEventListener()和attachEvent()两种事件监听方法的异同,涵盖了事件绑定、执行顺序、参数差异及事件流概念。并通过示例展示了如何在不同浏览器下进行事件监听的兼容处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

addEventListener()和attachEvent()相同点和不同点

相同点:
① 它们都是dom对象的方法,可以实现一种事件绑定多个事件处理函数;
② 相对于普通的DOM事件处理element.event = fun();的写法来说,使用attachEvent和addEventListener时则可以实现多个事件处理函数的调用;

不同点:
① attachEvent是IE有的方法,它不遵循W3C标准,而其他的主流浏览器如FF等遵循W3C标准的浏览器都使用addEventListener,所以实际开发中需分开处理 — 涉及兼容;
② 多次绑定后执行的顺序是不一样的,attachEvent是后绑定先执行,addEventListener是先绑定先执行;
③ 绑定时间时,attachEvent必须带on,如onclick,onmouseover等,而addEventListener不能带on,如click,mouseover ;
④ attachEvent仅需要传递两个参数,而addEventListener需要传递三个参数,这里牵扯到“事件流”的概念。侦听器在侦听时有三个阶段:捕获阶段、目标阶段和冒泡阶段。顺序为:捕获阶段(根节点到子节点检查是否调用了监听函数)→目 标阶段(目标本身)→冒泡阶段(目标本身到根节点)。此处的参数确定侦听器是运行于捕获阶段、目标阶段还是冒泡阶段。 如果将 useCapture 设置为 true,则侦听器只在捕获阶段处理事件,而不在目标或冒泡阶段处理事件。 如果useCapture 为 false,则侦听器只在目标或冒泡阶段处理事件。 要在所有三个阶段都侦听事件,请调用两次 addEventListener,一次将 useCapture 设置为 true,第二次再将useCapture 设置为 false;

关于 ④ 的理解可以转至:点这里(讲解一下这两个参数顺便补一下事件冒泡和事件捕获的概念理解)

例子:

// 普通事件处理函数 --- 只执行最后一个事件绑定函数(只执行最后绑定的事件回调 >>> 3)
        btn.onclick = function(){alert(1);}
        btn.onclick = function(){alert(2);}
        btn.onclick = function(){alert(3);}
// attachEvent事件处理函数调用 --- 后绑定先执行(IE8- >>> 3 2 1)
        btn1.attachEvent("onclick",function(){ alert(1); })
        btn1.attachEvent("onclick",function(){ alert(2); })
        btn1.attachEvent("onclick",function(){ alert(3); })
 // addEventListener事件处理函数 --- 先绑定先执行(IE9+/主流浏览器 >>> 1 2 3)
        btn2.addEventListener("click",function(){ alert(1); },false)
        btn2.addEventListener("click",function(){ alert(2); },false)
        btn2.addEventListener("click",function(){ alert(3); },false)
封装 – 不同浏览器监听事件和清除事件的方法
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button id="btn">点我</button>
</body>
<script type="text/javascript">
/**对监听事件做兼容处理
 * 参数解释:
 * element: 监听事件源
 * type: 为监听事件名,如click,submit等
 * handler: 为监听事件所执行的函数
 * 调用: EventUtil.addHandler(添加事件)/removeHandler(移除事件)
 */
    var EventUtil = {
        addHandler : function(type, handler, element){
			this.checked(type, handler, element);
            if(element.addEventListener){
                element.addEventListener(type, handler, false);
            }else if(element.attachEvent){
                element.attachEvent('on' + type, handler);
            }else{
                element['on' + type] = handler;
            }
        },
        removeHandler : function(type, handler, element){
        	this.checked(type, handler, element);
            if(element.removeEventListener){
                element.removeEventListener(type, handler, false);
            }else if(element.detachEvent){
                element.detachEvent('on' + type, handler);
            }else{
                element['on' + type] = null;
            }
        },
        checked: function(type, handler, element){
        	if(!(typeof(type) == 'string')) throw new Error("The parameter is required and the parameter type is String");
        	if(!(handler instanceof Function)) throw new Error("The parameter is required and the parameter type is Function");
        	return element = element ? element : document;
        }
    }
    var a = 111;
    var btn = document.getElementById('btn');
    var handler = function(){
        console.log('Hello World!');
        /* 移除事件 */
        // EventUtil.removeHandler(btn,'click',handler);
    }
    /* 添加事件 */
    EventUtil.addHandler('click', handler, btn);
</script>
</html>
使用哈希值-表封装
function addEvent(element, type, handler) {
            //为每一个事件处理函数分派一个唯一的ID
            if (!handler.$$guid) handler.$$guid = addEvent.guid++;
            //为元素的事件类型创建一个哈希表
            if (!element.events) element.events = {};
            //为每一个"元素/事件"对创建一个事件处理程序的哈希表
            var handlers = element.events[type];
            if (!handlers) {
                handlers = element.events[type] = {};
                //存储存在的事件处理函数(如果有)
                if (element["on" + type]) {
                    handlers[0] = element["on" + type];
                }
            }
            //将事件处理函数存入哈希表
            handlers[handler.$$guid] = handler;
            //指派一个全局的事件处理函数来做所有的工作
            element["on" + type] = handleEvent;
        };
        //用来创建唯一的ID的计数器
        addEvent.guid = 1;
        function removeEvent(element, type, handler) {
            //从哈希表中删除事件处理函数
            if (element.events && element.events[type]) {
                delete element.events[type][handler.$$guid];
            }
        };
        function handleEvent(event) {
            var returnValue = true;
            //抓获事件对象(IE使用全局事件对象)
            event = event || fixEvent(window.event);
            //取得事件处理函数的哈希表的引用
            var handlers = this.events[event.type];
            //执行每一个处理函数
            for (var i in handlers) {
                this.$$handleEvent = handlers[i];
                if (this.$$handleEvent(event) === false) {
                    returnValue = false;
                }
            }
            return returnValue;
        };
        //为IE的事件对象添加一些“缺失的”函数  --  冒泡兼容IE的处理
        function fixEvent(event) {
            //添加标准的W3C方法
            event.preventDefault = fixEvent.preventDefault;
            event.stopPropagation = fixEvent.stopPropagation;
            return event;
        };
        fixEvent.preventDefault = function () {
            this.returnValue = false;
        };
        fixEvent.stopPropagation = function () {
            this.cancelBubble = true;
        };
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值