ExtJS全局事件监听器异常:关闭窗口后触发仍报错
问题根源与解决方案
你碰到的这个问题本质是全局事件监听器没有和窗口组件的生命周期绑定,导致窗口销毁后监听器依然在执行。
为什么会出现这个问题?
当你用Ext.on('translated', ...)注册全局事件时,这个监听器是挂载到Ext的全局事件总线上的,完全独立于你的Info窗口实例。哪怕窗口已经关闭甚至被销毁,这个监听器还是会留在事件总线里——每次触发translated事件,它都会尝试执行回调。而此时窗口实例已经失效,me指向的组件不存在了,调用me.down()自然会抛出错误。
顺带提一句:如果你的窗口closeAction是默认的'hide'(关闭时只是隐藏而非销毁),第一次关闭可能不会报错,但一旦窗口后续被销毁,同样会触发这个问题。
修复方案(两种可选)
方案1:使用Managed Listeners(推荐)
Ext提供了mon(Managed ON)方法,用它注册的监听器会在组件销毁时自动被清理,不用手动处理。把你原来的Ext.on改成this.mon即可:
initComponent: function() { // ... 原有代码 ... var me = this; // 替换原来的Ext.on,改用mon绑定到全局事件 this.mon(Ext.GlobalEvents, 'translated', function() { me.down('panel[name=moreinformation]').setHtml(me.updateInfo()); }); // ... 原有代码 ... }
这样窗口销毁时,这个监听器会被自动移除,不会再触发无效的回调。
方案2:手动管理监听器
如果你更习惯手动控制,可以保存Ext.on返回的监听器引用,然后在窗口销毁时手动移除:
initComponent: function() { // ... 原有代码 ... var me = this; // 保存监听器对象 var translatedListener = Ext.on('translated', function() { me.down('panel[name=moreinformation]').setHtml(me.updateInfo()); }); // 监听窗口销毁事件,移除全局监听器 this.on('destroy', function() { Ext.un('translated', translatedListener); }); // ... 原有代码 ... }
额外优化建议
如果你的窗口关闭后不需要保留实例,建议设置closeAction: 'destroy',这样点击关闭按钮时窗口会直接销毁,而不是隐藏,避免不必要的内存占用:
Ext.define('Project.view.window.Info', { extend: 'Ext.window.Window', layout: 'fit', constrain: true, closeAction: 'destroy', // 添加这一行 // ... 原有代码 ... });
结合上面的监听器管理方案,就能彻底解决这个问题了。
内容的提问来源于stack exchange,提问作者E.Scott
相关产品推荐
相关产品推荐

