移除通过类添加的事件监听器(ExtJS 3.4 问题求助)
我之前踩过ExtJS 3.4事件移除的坑,跟4.x的差异真的挺闹心的。针对你说的div#mainMenu移除类相关事件监听器的问题,给你几个纯JavaScript的解决方案,分情况来处理:
情况1:事件是通过ExtJS 3.4官方API绑定的
比如你用了Ext.EventManager.on('mainMenu', 'click', handlerFn)或者Ext.get('mainMenu').on('mouseover', handlerFn)这类方法绑定事件,ExtJS 3.x会把处理函数包装后存在DOM元素的私有_events属性里,直接用原生removeEventListener大概率无效——因为你拿的handler不是Ext实际绑定的那个。可以用这段代码来处理:
var mainMenu = document.getElementById('mainMenu'); var targetEventType = 'click'; // 替换成你要移除的事件类型,比如mouseover、mouseout // 检查Ext是否在该元素上存储了事件数据 if (mainMenu._events && mainMenu._events[targetEventType]) { // 复制事件数组避免遍历过程中修改原数组导致的问题 var eventHandlers = [...mainMenu._events[targetEventType]]; eventHandlers.forEach(function(eventEntry) { var actualHandler = eventEntry.fn; // 适配不同浏览器的事件移除方法 if (mainMenu.removeEventListener) { mainMenu.removeEventListener(targetEventType, actualHandler, false); } else if (mainMenu.detachEvent) { // 兼容IE旧版本 mainMenu.detachEvent('on' + targetEventType, actualHandler); } }); // 清空Ext存储的该类型事件列表 delete mainMenu._events[targetEventType]; }
情况2:事件是通过类选择器做的委托绑定
如果事件是绑定在父元素上,通过类选择器(比如.mainMenu)委托到目标div的,你没法直接移除单个元素的委托事件,只能修改委托逻辑,让它不再响应#mainMenu:
var mainMenu = document.getElementById('mainMenu'); var delegateParent = document; // 替换成实际的委托父元素(比如某个容器div) var targetEventType = 'click'; // 注意:getEventListeners仅在Chrome/Firefox开发者工具环境下可用,生产环境可以用其他方式遍历事件 if (typeof getEventListeners === 'function') { var parentListeners = getEventListeners(delegateParent)[targetEventType] || []; parentListeners.forEach(function(listener) { var originalHandler = listener.listener; // 先移除原委托监听器 delegateParent.removeEventListener(targetEventType, originalHandler, listener.useCapture); // 添加新的监听器,过滤掉#mainMenu的事件 delegateParent.addEventListener(targetEventType, function(e) { var eventTarget = e.target; // 判断事件触发目标是不是#mainMenu或者它的子元素 if (eventTarget !== mainMenu && !mainMenu.contains(eventTarget)) { originalHandler.call(this, e); } }, listener.useCapture); }); }
几个关键提醒
- 匿名函数没法直接移除:如果绑定事件时用的是匿名函数(比如
Ext.get('mainMenu').on('click', function(){/* 逻辑 */})),你没法通过引用找到它,这时候只能用上面清空所有同类型事件的方式,或者重新绑定新逻辑覆盖。 - 为什么4.x没问题:ExtJS 4.x完全重构了事件系统,
un()方法能精准定位并移除监听器,事件存储结构也更规范,所以不会出现3.x这种“移除无效”的情况。
内容的提问来源于stack exchange,提问作者Karthik
相关产品推荐
相关产品推荐

