我在主窗口上监听onload
事件,然后在每个浏览器/选项卡上监听DOMContentLoaded
事件(我需要在浏览器中最多运行代码)并标记为{{ 1}}代码是在浏览器上运行的。
controlExecuted
这不起作用。代码运行多次,具体取决于浏览器/标签的数量。
那么如何在firefox插件中只运行一个代码实例?
答案 0 :(得分:1)
正如您所注意到的,每次打开新的浏览器窗口时,您的代码都会运行。您可能没有意识到的是,一个窗口中的脚本在另一个窗口中完全独立相同的脚本。也就是说,每次都会实例化一组新对象,这意味着一个窗口中的controlExecuted
与另一个窗口中的controlExecuted
不是同一个对象。
在扩展程序中共享代码有两种方法:
创建XPCOM component。这是在浏览器扩展中共享代码的经典,更难(但非常强大)的方法。
创建JavaScript code module(JSM)。简而言之:
JavaScript代码模块是Gecko 1.9中引入的概念,可以 用于在不同的特权范围之间共享代码。模块 也可用于创建全局JavaScript单例 以前需要使用JavaScript XPCOM对象。
您也可以考虑将此标记设置为用户首选项,您的脚本的每个实例都可以读取该标记。对于这样一个简单的用例,这可能是最简单的方法。
答案 1 :(得分:1)
这是使用JavaScript code modules在firefox插件中仅运行一个代码实例的完整解决方案。
// modules/main.jsm
var EXPORTED_SYMBOLS = ["instancesControl"];
var instancesControl = {
executed : 0,
windowExecuting : 0,
get : function(){
return ++instancesControl.executed;
},
reset : function(){
instancesControl.executed = 0;
},
getWindowExecuting : function(){
return instancesControl.windowExecuting;
},
setWindowExecuting : function(id){
instancesControl.windowExecuting = id;
}
};
主要呼叫代码:
// load instancesControl module
Components.utils.import("resource://my-own-alias/main.jsm");
// identify window that will execute the one-instance code
var util = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var windowID = util.outerWindowID;
// listen load window event
window.addEventListener("load", function(){
var appcontent = document.getElementById("appcontent");
if (appcontent){
// listen load content (on every tab)
appcontent.addEventListener("DOMContentLoaded", function docLoader(e){
appcontent.removeEventListener("DOMContentLoaded", docLoader, false);
if (instancesControl.get() == 1){
instancesControl.setWindowExecuting(windowID);
// this code will run only once no matter
// how many tabs or windows user opens.
}
}, true);
}
}, false);
// re-init code if executing windows is closed
window.addEventListener("unload", function(){
if (instancesControl.getWindowExecuting() == windowID){
instancesControl.reset();
}
}, false);
当然可以改进它。如果你这样做,请使用@nomikos进行评论 THX。