不,没有明智的方法可以避免事件侦听器的性能优于另一个事件侦听器,并且与在会话中卸载加载项兼容。
挂钩nsContextMenu
正如您已经被告知的,状态是通过初始化的gContextMenu = new nsContextMenu(...)
。所以你需要钩住这些东西,这实际上很容易。
var newProto = Object.create(nsContextMenu.prototype);
newProto.initMenuOriginal = nsContextMenu.prototype.initMenu;
newProto.initMenu = function() {
let rv = this.initMenuOriginal.apply(this, arguments);
console.log("ctx", this.onImage, this); // Or whatever code you'd like to run.
return rv;
};
nsContextMenu.prototype = newProto;
现在,第一个问题是:它实际上表现更好吗?毕竟这只是在原型链中引入了另一个链接。当然,可以避免Object.create
并直接覆盖nsContextMenu.prototype.initMenu
。
但真正的问题是:如何再次移除钩子?回答:你真的不能,因为其他插件可能在你之后钩住了同样的东西,而解钩也会解钩其他插件。但是您需要摆脱引用,否则加载项在禁用/卸载时会泄漏内存。好吧,您可以使用Components.utils.makeObjectPropsNormal
,但这对封闭变量并没有真正的帮助。所以让我们避免闭包...嗯...您需要某种消息传递,例如事件侦听器或观察器...我们回到第一个问题。
另外,与
document.getElementById("contentAreaContextMenu").addEventListener(...)
我将其称为“为没有可衡量的利益而过度杀戮”。
覆盖onpopupshowing=
可以覆盖<menupopup onpopupshowing=
. 是的,这可能会飞......除了其他附加组件可能有相同的想法,所以欢迎来到兼容性地狱。此外,这再次涉及将东西推入窗口,这会导致跨隔间包装,这会使事情再次容易出错。
这是一个解决方案吗?也许,但不是一个理智的人。
还有什么?
不多,真的。