继removeEventListener in bootstrapped addon not working when addon disabled之后,我正在探索其他可能性。
除了使用 bind()
并缓存绑定(bind)函数,有没有办法使用“this”并传递参数?
// works fine but can't pass argeement
contextMenu.addEventListener('popupshowing',
this.contextPopupShowing, false);
// passes the argument but 'this' is no longer available
contextMenu.addEventListener('popupshowing',
function(){this.contextPopupShowing(window);}, false);
我一直在使用许多事件监听器 bind()
我正在寻找不使用 bind()
的替代方法
我什至试图捕获 window
具有来自 <menupopup id="contentAreaContextMenu" ...>
的递归函数
更新: bind()
干扰 removeEventListener
最佳答案
因为我们谈论的是无重启附加组件...许多无重启附加组件使用 unload
和 unloadWindow
辅助函数,以使其更容易实现 shutdown
并帮助处理诸如 addEventListener
之类的事情,所以请耐心等待。
助手 - unload
首先,unload
是一个辅助函数,您可以将另一个函数传递给该函数,它将在 shutdown
时运行(或者可以手动调用)。大多数实现都与此极为相似:
var unloaders = []; // Keeps track of unloader functions.
function unload(fn) {
if (typeof(fn) != "function") {
throw new Error("unloader is not a function");
}
unloaders.push(fn);
return function() {
try {
fn();
}
catch (ex) {
Cu.reportError("unloader threw " + fn.toSource());
Cu.reportError(ex);
}
unloaders = unloaders.filter(function(c) { return c != fn; });
};
}
然后您可以连接shutdown
来做正确的事情:
function shutdown() {
...
for (let i = unloaders.length - 1; i >= 0; --i) {
try {
unloaders[i]();
}
catch (ex) {
Cu.reportError("unloader threw on shutdown " + fn.toSource());
Cu.reportError(ex);
}
}
unloaders.length = 0;
}
使用卸载
现在您可以执行以下操作:
function startup() {
setupSomething();
unload(removeSomething);
setupSomethingElse();
var manualRemove = unload(removeSomethingElse);
...
if (condition) {
manualRemove();
}
}
助手 - unloadWindow
您通常需要创建第二个函数 unloadWindow
以在您的附加组件关闭或窗口关闭时卸载内容,无论先发生什么。当窗口关闭时不删除东西可能非常棘手,并创建 Zombie compartments您的 bootstrap.js
和/或代码模块非常容易(这是来自编写和审查无重启附加组件的经验)。
function unloadWindow(window, fn) {
let handler = unload(function() {
window.removeEventListener('unload', handler, false);
try {
fn();
}
catch (ex) {
Cu.reportError("window unloader threw " + fn.toSource());
Cu.reportError(ex);
}
});
window.addEventListener('unload', handler, false);
};
(有些人可能想“优化”这个,因为只有一个 “unload”
处理程序,但通常你只有这样的 unloadWindow
调用它不会'没关系。)
综合考虑
现在您可以.bind
东西并做任何事情并让卸载程序闭包跟踪它。此外,您可以使用它来将关闭代码放在初始化代码旁边,这可能会增加可读性。
function setupWindow(window, document) {
var bound = this.contextPopupShowing.bind(this);
contextMenu.addEventListener('popupshowing', bound, false);
unloadWindow(window, function() {
contextMenu.removeEventListener('popupshowing', bound, false);
});
// Or stuff like
var element = document.createElement(...);
contextMenu.appendChild(element);
unloadWindow(window, function() {
contextMenu.removeChild(element);
});
// Or just combine the above into a single unloader
unloadWindow(window, function() {
contextMenu.removeEventListener('popupshowing', bound, false);
contextMenu.removeChild(element);
});
}
关于javascript - 在不使用绑定(bind)的情况下将 'this' 和参数传递给 addEventListener 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24473309/