JavaScript 事件处理封装与兼容性实现详解

作者:像素漫游时间:2026-10-28 19:07:26浏览:97

本文分享一个JavaScript事件处理工具类EventUtil,旨在解决跨浏览器事件兼容性问题。代码封装了添加、移除、加载及阻止事件的方法,特别针对IE8及以下版本提供了attachEvent和window.event的兼容处理。文章还解析了事件捕获、处理、起泡三阶段机制,并提供了多种获取事件源对象的方法,适用于需要统一事件行为的前端开发场景。

JavaScript事件处理封装与兼容性实现详解

本文直接展示核心实现代码,省略冗余说明。

具体实现如下:

<script type="text/javascript">
function EventUtil() {
var _self = this;
///添加事件
var addEvent = (function () {
if (document.addEventListener) {
return function (el, type, fn) {
el.addEventListener(type, fn, false);
                }
} else {
return function (el, type, fn) {
el.attachEvent("on" + type, function () {
return fn.call(el, window.event);
                    });
                }
            }
        })();
///添加属性改变事件
var addPropertyChangeEvent = function (obj, fn) {
if (window.ActiveXObject) {
obj.onpropertychange = fn;
} else {
obj.addEventListener("input", fn, false);
            }
        }
//移除事件
var removeEvent = function (obj, type, fn) {
if (obj.removeEventListener) {
obj.removeEventListener(type, fn, false);
} else if (obj.detachEvent) {
obj.detachEvent("on" + type, obj["on" + type + fn]);
obj["on" + type + fn] = null;
            }
        }
//加载事件
var loadEvent = function (fn) {
var oldonload = window.onload;
if (typeof oldonload != "function") {
window.onload = fn;
} else {
window.onload = function () {
oldonload();
fn();
                }
            }
        }
//阻止事件
var stopEvent = function (e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
e.stopPropagation();
} else {
e.returnValue = false;
e.cancelBubble = true;
            }
        }
//如果仅仅是阻止事件冒泡
var stopPropagation = function (e) {
e = e || window.event;
if (!+"\v1") {
e.cancelBubble = true;
} else {
e.stopPropagation();
            }
        }
//取得事件源对象
var getEvent1 = function (e) {
e = e || window.event;
var obj = e.srcElement ? e.srcElement : e.target;
return obj;
        }
//取得事件源对象
var getEvent2 = function (e) {
if (window.event) return window.event;
var c = getEvent2.caller;
while (c.caller) {
c = c.caller;
            }
return c.arguments[0];
        }
//或者这个功能更强大
var getEvent3 = function (e) {
var e = e || window.event;
if (!e) {
var c = this.getEvent3.caller;
while (c) {
e = c.arguments[0];
if (e && (Event == e.constructor || MouseEvent == e.constructor)) {
break;
                    }
c = c.caller;
                }
            }
var target = e.srcElement ? e.srcElement : e.target,
currentN = target.nodeName.toLowerCase(),
parentN = target.parentNode.nodeName.toLowerCase(),
grandN = target.parentNode.parentNode.nodeName.toLowerCase();
return [e, target, currentN, parentN, grandN];
        }
_self.addEvent = addEvent;
 _self.addPropertyChangeEvent = addPropertyChangeEvent;
 _self.removeEvent = removeEvent;
 _self.loadEvent = loadEvent;
 _self.stopEvent = stopEvent;
 _self.stopPropagation = stopPropagation;
 _self.getEvent1 = getEvent1;
 _self.getEvent2 = getEvent2;
 _self.getEvent3 = getEvent3;
 }
 var eventUtil = new EventUtil();
 eventUtil.loadEvent(function () {
 eventUtil.addEvent(document, "click", function (e) {
 alert(eventUtil.getEvent3(e));
 });
 eventUtil.addPropertyChangeEvent(document,function(e){
 alert(eventUtil.getEvent3(e));
 });
 });
</script>

JavaScript事件处理机制通常包含三个阶段:捕获阶段、处理阶段和起泡阶段。

以点击按钮为例: 捕获阶段:由外层到内层,首先调用给Window注册的click捕获阶段监听方法,然后document、body、一层层的父节点,一直到按钮本身。

处理阶段:调用按钮本身的click监听方法。

起泡阶段:从按钮开始,从内层到外层,依次调用各级父节点的起泡阶段监听方法,直到Window。

但是,对于IE8及更低版本IE,不支持捕获阶段,因此捕获阶段的事件监听目前尚不通用。

通常的事件处理方法形式为:

代码如下:

function eventHandler(e) {
e = e || window.event;
var target = e.target || e.srcElement;
    ... ...  
      
}  

e为事件对象,当事件触发时,作为参数传进来,但对于IE8及更低版本IE不适用,只能通过全局的event变量访问,好在不会出现同时处理两个事件的情况。

作者最新文章