将消息从 background.js 传递到 popup.js
Posted
技术标签:
【中文标题】将消息从 background.js 传递到 popup.js【英文标题】:Passing message from background.js to popup.js 【发布时间】:2012-08-29 05:26:03 【问题描述】:我正在尝试实现我自己的 chrome 扩展,在某个事件上,创建一个浏览器通知并使用在 background.js 中计算的数据填充弹出窗口
这是我的manifest.json
文件:
"name": "Dummy name",
"description": "Description",
"manifest_version": 2,
"version": "1.1.3",
"icons":
"16": "icon_16.png",
"48": "icon_48.png",
"128": "icon_128.png",
"256": "icon_256.png"
,
"browser_action":
"default_icon": "icon_48.png",
"default_title": "Test",
"default_popup": "popup.html"
,
"permissions": ["background","webRequest","webRequestBlocking","webNavigation","tabs","notifications"],
"background":
"scripts":["jquery-1.8.1.min.js","classy.js","background.js"]
我在background.js
中给sendMessage
打电话
show : function(result)
var that = this;
chrome.extension.sendMessage(greeting: "hello", function(response)
console.log(response);
);
if(window.webkitNotifications)
var notification = webkitNotifications.createHTMLNotification('notification.html');
notification.show();
setTimeout(function()
notification.cancel();
, '7000');
我在popup.js
中的消息监听器(来自 chrome 扩展示例)
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse)
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse(farewell: "goodbye");
);
我得到的唯一错误是
端口错误:无法建立连接。接收端不 存在。
感谢您的帮助!
【问题讨论】:
后台页面加载很久才显示浏览器动作弹窗。显然,弹出脚本没有更改通过chrome.extension.onMessage
绑定事件监听器。
如前所述,这是基于事件触发的。由于事件发生在页面加载后的几秒钟内,是否仍然可以相信它没有被弹出窗口收听?
确保你说的是真的。您可以输入一个alert('')
对话框来查看这些方法是否以预期的顺序出现。旁注,您可以通过chrome.extension.getBackgroundPage()
(从弹出窗口访问后台的全局window
对象)和chrome.extension.getViews(type:'popup')[0]
(如果存在弹出窗口的全局window
对象,从背景页面)。
我刚刚对此进行了测试,实际上,弹出窗口中的任何操作都只能在它打开时触发。知道如何模拟消息发送吗?不幸的是,它与 getBackgroundPage() 和 getViews() 相同...仅在弹出窗口打开时起作用:(
“显然”也已被弃用,应避免使用。
【参考方案1】:
本地存储解决方案
由于弹出窗口没有持久状态,您可能希望使用 localStorage 存储弹出窗口状态并在弹出窗口打开时预加载它,并使用storage
事件来跟踪弹出窗口打开时状态的更改。
背景:
localStorage.setItem('popupData', JSON.stringify( tabReady: true ));
弹出窗口:
// Load the state from localStorage when popup opens
let popupData = JSON.parse(localStorage.getItem('popupData'));
// Keep track of changes to the popup state while the popup is open
window.addEventListener('storage', (e) =>
if (e.key === 'popupData')
popupData = JSON.parse(e.newValue);
console.log(popupData.tabReady);
);
【讨论】:
【参考方案2】:这是我发现的将数据从 background.js 发送到 popup.js 的两种最简单的方法:
1) 使用存储
将值保存到存储中,一旦弹出窗口打开,它会从存储中获取值并将它们显示在弹出窗口中。
background.js
chrome.storage.sync.set( 'dataValue1': 'Some data 1.' );
chrome.storage.sync.set( 'dataValue2': 'Some data 2.' );
popup.js
function updatePopup()
chrome.storage.sync.get(['dataValue1', 'dataValue2'], function (data)
document.getElementById("popupElement1").innerText = data.dataValue1;
document.getElementById("popupElement2").innerText = data.dataValue2;
);
document.addEventListener('DOMContentLoaded', updatePopup);
popup.html
<html>
<head>
<script src="popup.js"></script>
</head>
<body>
<p id="popupElement1"></p>
<p id="popupElement2"></p>
</body>
</html>
manifest.json
"name": "Background2popup",
"version": "1.0",
"manifest_version": 2,
"description": "This is a demo",
"browser_action":
"default_popup": "popup.html"
,
"background":
"scripts": [
"background.js"
]
,
"permissions": [
"<all_urls>",
"storage",
"tabs"
]
2) 使用 chrome.runtime.sendMessage()
一旦弹出窗口打开,您会从弹出窗口向后台发送消息以建立连接/握手(否则,您将收到“未检查的 runtime.lastError:无法建立连接。接收端不存在。”如果您尝试从后台发送消息到弹出窗口并且弹出窗口未打开)。建立连接后,您首先使用后台的 sendResponse 将要发送的数据发送到弹出窗口。
background.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse)
if (request.method == "getStatus")
console.log(request.data)
sendResponse( method: "peepee", data: "poopoo" )
);
popup.js
chrome.runtime.sendMessage( method: "getStatus", data: "xxx" , function (res)
document.getElementById("popupElement1").innerText = res.method;
document.getElementById("popupElement2").innerText = res.data;
return true;
);
popup.html & manifest.json 与第一个示例相同
【讨论】:
【参考方案3】:弹出窗口没有标签 ID,因此您会收到错误消息。
在这种情况下,您可以使用chrome.runtime.sendMessage
和chrome.runtime.onMessage.addListener
。
所以在 background.js
chrome.runtime.sendMessage(
msg: "something_completed",
data:
subject: "Loading",
content: "Just completed!"
);
而在 popup.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse)
if (request.msg === "something_completed")
// To do something
console.log(request.data.subject)
console.log(request.data.content)
);
希望对你有帮助。
谢谢,
【讨论】:
如果我打开了多个选项卡并向 popup.js 发送消息怎么办。哪个 popup.js 会收到它?如何将消息发送到我想发送消息的地方@Perfect 您应该将消息从弹出窗口发送到后端脚本。此时,您可以在后端脚本中获取 tab_id 来识别哪个选项卡的弹出窗口发送到后台。无法将消息从后端脚本发送到弹出窗口,但您可以将后端脚本发送到特定选项卡的内容脚本。或者您可以在后端和弹出窗口之间创建连接。看看这个链接。 ***.com/questions/13546778/… 我在看到这个之前使用 tabid 做了完全相同的事情。感谢@Perfect 提供另一种方式【参考方案4】:要解决这个问题,您需要先向 background.js 发送握手消息,然后将实际数据从 background.js 发送到 popup.js 例如:就我而言,我所做的是
popup.js
chrome.runtime.sendMessage(data:"Handshake",function(response)
);
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse)
str = JSON.stringify(message.data);
);
background.js
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse)
//alert(message.data);
chrome.runtime.sendMessage(data:datax,function(response)
);
);
我试图做的是,只要我们点击图标,握手消息就会发送到 background.js,当它收到它时,我们可以发送变量或我们想要发送的任何数据到 popup.js在 popup.html 上呈现它。
【讨论】:
我喜欢握手的想法,它确保弹出窗口是活动的(没有被破坏)并且能够监听传入的数据。此外,这似乎是每个页面加载的一次性事件,它遵循 API 的 Simple one-time request methods 但这意味着调用是由Popup发起的。我相信 OP 想要从背景到弹出的对话启动。如果弹出窗口想从后台提取数据,它也可以执行以下标准方法: let bg= chrome.runtime.getBackgroundPage() 然后通过 console.log(bg.message) 获取 msg;这里的“消息”是 background.js 文件中的一个对象【参考方案5】:使用runtime.sendMessage
将消息发送到后台脚本,使用tabs.sendMessage
从后台发送到内容脚本。
请注意,您需要指定标签ID:
chrome.tabs.query( active: true , (tabs) =>
chrome.tabs.sendMessage(tabs[0].id, greeting: 'hello' , (response) =>
console.log(response);
);
);
您可以在此处找到完整的示例和文档:https://developer.chrome.com/extensions/messaging#simple
【讨论】:
以上是关于将消息从 background.js 传递到 popup.js的主要内容,如果未能解决你的问题,请参考以下文章
Angular 6 - 通过服务将消息传递到从组件到消息组件