我有一個Firefox覆蓋擴展和側欄中的一棵樹。 如何保持樹狀態在多個窗口中同步? 例如在第一個窗口中添加了新的項目樹,如何更新其他窗口中的樹?Firefox擴展:共享狀態
如果有人可以顯示最少的代碼(使用代碼模塊,觀察者,廣播或其他),請幫助。
我看過類似的問題,但它並沒有幫助: Firefox extension - Share common state between two or more windows
我有一個Firefox覆蓋擴展和側欄中的一棵樹。 如何保持樹狀態在多個窗口中同步? 例如在第一個窗口中添加了新的項目樹,如何更新其他窗口中的樹?Firefox擴展:共享狀態
如果有人可以顯示最少的代碼(使用代碼模塊,觀察者,廣播或其他),請幫助。
我看過類似的問題,但它並沒有幫助: Firefox extension - Share common state between two or more windows
在你參考這個問題的答案是好的,但短期上的解釋。您應該閱讀它鏈接的參考。我在這裏複製了這些鏈接。
保持窗口上下文以外狀態信息的一種方法是使用JavaScript code modules(JSM)。部分Sharing objects using code modules簡要介紹瞭如何做到這一點。一旦建立了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);
}
然後在側邊欄的代碼:
//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;
}
重構上面的第一個代碼段,這樣它看起來是一個模塊使用一個變量來減少命名空間混亂。該模塊的代碼可能是這樣的:
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代碼找到您的代碼所在的側欄(以便發送或收聽事件)可能比您想象的要複雜一些。你應該看到Working with windows in chrome code。具體而言,Accessing the elements of the top-level document from a child window。這部分提供了下面的代碼來從一個側邊欄內訪問主瀏覽器窗口中:
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)' – Noitidart 2014-10-20 15:09:28