【发布时间】:2012-03-02 17:09:50
【问题描述】:
有没有办法在popup.html(或popup.js)和后台脚本之间传递信息?
我希望弹出窗口显示来自用户帐户的信息或允许他们登录,但让 background.js 处理身份验证和其他逻辑。我在清单中声明了 background.js,但似乎根本没有迹象表明它正在被使用。
编辑:如果我把这一切都搞错了,并且有更好的方法来做到这一点,那也很棒。
【问题讨论】:
有没有办法在popup.html(或popup.js)和后台脚本之间传递信息?
我希望弹出窗口显示来自用户帐户的信息或允许他们登录,但让 background.js 处理身份验证和其他逻辑。我在清单中声明了 background.js,但似乎根本没有迹象表明它正在被使用。
编辑:如果我把这一切都搞错了,并且有更好的方法来做到这一点,那也很棒。
【问题讨论】:
注意后台页面和弹窗在同一个进程(扩展进程),所以一个页面可以获取另一个页面的DOM窗口,然后直接调用函数或设置变量。比如弹窗可以调用chrome.extension.getBackgroundPage修改背景:
chrome.extension.getBackgroundPage().variable = 42;
后台页面可以调用chrome.extension.getViews获取弹窗:
var popups = chrome.extension.getViews({type: "popup"});
if (0 < popups.length)
popups[0].variable = 42;
另一种设置共享变量的方法是使用传统的 DOM API,因为每个扩展都有一个虚假的来源(例如“eakjnniffhfegdpfehmnpcmjiameincp”)。所以当你在后台修改localStorage、document.cookie或IndexedDB时,可以在弹窗中读回。
也就是说,即使在扩展过程中的页面内,您可能仍希望使用消息传递 API,因为它可能会使您的代码更加统一。消息传递是与内容脚本通信的唯一方式。
【讨论】:
您可以来回发送请求,甚至更好地使用端口进行持续通信。
我给出的示例将在弹出窗口和打开弹出窗口时连接的背景页面之间创建双向通信。
只需创建一个包含在背景页面和弹出页面中的 socket.js 文件。然后在每个你都可以声明:
new Socket();
这里是socket.js的实现:
var Socket = function() {
window.socket = this;
this.port = chrome.extension.connect({name:"popupToBackground"});
chrome.extension.onConnect.addListener(function(port) {
if(port.name == "backgroundToPopup") {}
else if(port.name == "popupToBackground") {
window.socket.port = chrome.extension.connect({name:"backgroundToPopup"});
}
else {
return;
}
port.onMessage.addListener(function(msg) {
try {
window[msg.namespace][msg.literal][msg.method].apply(this, msg.args);
}
catch(error) {
// your failed action goes here.
}
});
});
};
确保让消息侦听器中的通用方法调用为您工作。我喜欢上面给出的格式——它非常健壮。要来回发送消息,只需将它们发布到套接字:
socket.post({ namespace: "myNamespace",
literal: "myLiteral",
method: "myMethod",
args: ["argOne", "argTwo"]
});
});
所以如果这是从弹出页面执行的,那么后台页面会调用:
window.myNamespace.myLiteral.myMethod(argOne, argTwo);
对我来说,这是一个非常好的可重用 javascript 对象。如果您愿意,您甚至可以添加特定的原型函数 - 这样发送消息更加容易:
Socket.prototype = {
sendOneTwo: function() {
socket.post({ namespace: "myNamespace",
literal: "myLiteral",
method: "myMethod",
args: ["argOne", "argTwo"]
});
};
现在你要说的是:
socket.sendOneTwo();
【讨论】:
出于调试目的,我发现这在弹出式 JS 中非常方便:
console = chrome.extension.getBackgroundPage().console
【讨论】: