Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Firefox扩展:共享状态_Firefox_Firefox Addon_State_Javascript - Fatal编程技术网

Firefox扩展:共享状态

Firefox扩展:共享状态,firefox,firefox-addon,state,javascript,Firefox,Firefox Addon,State,Javascript,我有一个Firefox覆盖扩展,在侧边栏中有一棵树。 如何在多个窗口中保持树状态同步? 例如,在第一个窗口中,在树中添加了新项,如何在其他窗口中更新树 如果有人可以为它显示最少的代码(使用代码模块、观察者、广播者或其他),请帮助 我读过类似的问题,但没有帮助: 你提到的问题的答案很好,但缺乏解释。你应该阅读它链接到的参考资料。我在这里复制了这些链接 将状态信息保留在窗口上下文之外的一种方法是使用(JSM)。本节简要介绍了如何做到这一点。一旦您设置了JSM来共享数据,只需通知每个窗口已经进行了更改

我有一个Firefox覆盖扩展,在侧边栏中有一棵树。 如何在多个窗口中保持树状态同步? 例如,在第一个窗口中,在树中添加了新项,如何在其他窗口中更新树

如果有人可以为它显示最少的代码(使用代码模块、观察者、广播者或其他),请帮助

我读过类似的问题,但没有帮助:

你提到的问题的答案很好,但缺乏解释。你应该阅读它链接到的参考资料。我在这里复制了这些链接

将状态信息保留在窗口上下文之外的一种方法是使用(JSM)。本节简要介绍了如何做到这一点。一旦您设置了JSM来共享数据,只需通知每个窗口已经进行了更改,并且应该更新显示的状态。这可以通过使用您定义的事件轻松实现。所有侧边栏都在其窗口中侦听特定事件。然后,JSM中有一个函数贯穿所有窗口,向它们发出需要更新的信号

发送信号的代码可能类似于:

Components.utils.import("resource://gre/modules/Services.jsm");

function forEachOpenWindow(todo) {
    // Apply a function to all open browser windows
    var windows = Services.wm.getEnumerator("navigator:browser");
    while (windows.hasMoreElements()) {
      todo(windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow));
    }
}

function signalUpdateNeeded(window){
    let event = window.document.createEvent("Event");
    event.initEvent("myExtensionName-UpdateAvailable",false,false);
    window.dispatchEvent(event);
}

function sendUpdateAvailableToAllWindows(){
    forEachOpenWindow(signalUpdateNeeded);
}
var EXPORTED_SYMBOLS = [ "myExtensionModule" ];
Components.utils.import("resource://gre/modules/Services.jsm");

var myExtensionModule = {
    dataStructure: {
        whatever: true,
        you: 1,
        want: ["here.", "It", "is", "your", "data."]
    };

    forEachOpenWindow: function(todo){
        // Apply a function to all open browser windows
        var windows = Services.wm.getEnumerator("navigator:browser");
        while (windows.hasMoreElements()) {
          todo(windows.getNext()
                      .QueryInterface(Components.interfaces.nsIDOMWindow));
        }
    },

    signalUpdateNeeded: function(window){
        let event = window.document.createEvent("Event");
        event.initEvent("myExtensionName-UpdateAvailable",false,false);
        window.dispatchEvent(event);
    },

    sendUpdateAvailableToAllWindows: function(){
        this.forEachOpenWindow(this.signalUpdateNeeded);
    }
}
然后在侧栏的代码中:

//This imports your JSM, it does not need the .jsm extension, you can use
//   whatever extension you want.
Components.utils.import("chrome://MyExtension/content/moduleName.jsm"); 

window.addEventListener("myExtensionName-UpdateAvailable",
                            updateDataFromModule, false);
//Instead you may need the following (or another way to get to the 
//  top window).  What is actually needed will depend on the context in
//  which your sidebar code is running. You should see below for code to
//  access the main browser window from within a sidebar.
//window.top.addEventListener("myExtensionName-UpdateAvailable",
//                            updateDataFromModule, false);


function updateDataFromModule(){
   //Whatever it is you need to do here.
   mylocalVariable = myExtensionModule.dataStructure.whatever;
}
重构上面的第一个代码部分,使其看起来像是在一个使用一个变量来减少名称空间混乱的模块中。模块的代码可能类似于:

Components.utils.import("resource://gre/modules/Services.jsm");

function forEachOpenWindow(todo) {
    // Apply a function to all open browser windows
    var windows = Services.wm.getEnumerator("navigator:browser");
    while (windows.hasMoreElements()) {
      todo(windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow));
    }
}

function signalUpdateNeeded(window){
    let event = window.document.createEvent("Event");
    event.initEvent("myExtensionName-UpdateAvailable",false,false);
    window.dispatchEvent(event);
}

function sendUpdateAvailableToAllWindows(){
    forEachOpenWindow(signalUpdateNeeded);
}
var EXPORTED_SYMBOLS = [ "myExtensionModule" ];
Components.utils.import("resource://gre/modules/Services.jsm");

var myExtensionModule = {
    dataStructure: {
        whatever: true,
        you: 1,
        want: ["here.", "It", "is", "your", "data."]
    };

    forEachOpenWindow: function(todo){
        // Apply a function to all open browser windows
        var windows = Services.wm.getEnumerator("navigator:browser");
        while (windows.hasMoreElements()) {
          todo(windows.getNext()
                      .QueryInterface(Components.interfaces.nsIDOMWindow));
        }
    },

    signalUpdateNeeded: function(window){
        let event = window.document.createEvent("Event");
        event.initEvent("myExtensionName-UpdateAvailable",false,false);
        window.dispatchEvent(event);
    },

    sendUpdateAvailableToAllWindows: function(){
        this.forEachOpenWindow(this.signalUpdateNeeded);
    }
}
我还没有实际测试过这个,所以可能有一些错误

让边栏代码访问主浏览器窗口,或者让JSM代码查找代码所在的边栏(以便发送或侦听事件)可能比您想象的要复杂一些。你应该看看。明确地该部分提供以下代码,用于从侧栏中访问主浏览器窗口:

var mainWindow = window
                   .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                   .getInterface(Components.interfaces.nsIWebNavigation)
                   .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
                   .rootTreeItem
                   .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                   .getInterface(Components.interfaces.nsIDOMWindow);

另一种方法是JSM在数据结构中保留对对象的引用,所有侧栏都将侦听器放在该对象上。这可能是它创建的对象。如果使用此方法并选择使用窗口,则需要确保在窗口关闭时释放引用的句柄。如果不这样做,可能会导致内存泄漏。

我的做法是使用
Services.wm.getEnumerator('navigator:browser')枚举窗口。
并在更新一个窗口时更新所有窗口。如果要将所有窗口作为目标,而不仅仅是浏览器窗口,请执行
getEnumerator(null)