Chrome 扩展程序界面页面与内容脚本之间的通信问题



菜鸟问题在这里:

上周我写了一个非常基本的Chrome扩展程序,其中弹出窗口.js通过以下方式向内容.js脚本发送消息(也许这不是最好的方式,但这里重要的是它有效。为什么它很重要?请耐心等待...

在弹出窗口中.js

someButton.addEventListener('click', (event) => {
chrome.tabs.executeScript(null, {
file: 'src/content.js',
}, () => {
connect();
});
});

后来:

function connect() {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const port = chrome.tabs.connect(tabs[0].id);
port.postMessage({ type: 'info', data: someValue });
})
}

在内容中.js

if (!chrome.runtime.onConnect.hasListeners()) {
chrome.runtime.onConnect.addListener((port) => {
port.onMessage.addListener((msg) => {
if (msg && msg.type == "info") {
// do some stuff
}
});
});
}

这奏效了,但我认为不是最好的方法。自上周以来,我一直在阅读更多内容,并且知道我相信正确的方法应该是这样的:

在弹出窗口中.js

chrome.tabs.query({ active: true, currentWindow: true },  (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {
type: "info",
someValue: value
});
});

在内容上.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.type == "info"){
sendResponse({ message: "some answer" }) 
}
return true;
})

但是在我的新版本中,这不起作用,即使每个教程和文档都说它应该。我没有收到任何错误,简单的函数添加到侦听器中,它永远不会被执行。

我怀疑也许可能与现在我正在使用 React 和 Webpack 有关,也许 Webpack 正在做一些奇怪的事情?

我的清单的片段.json

"background": {
"persistent": false,
"scripts": ["background.bundle.js"]
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content.bundle.js"]
}],

也许问题是我正在指定捆绑包的内容和背景?不确定,我唯一知道的是,根据我的理解,这应该有效,而事实并非如此。

我错过了什么?

PS:我应该补充一点,我一直在调试,我发现内容文件正在执行,并且发送消息的代码段也已执行。就像 addListener 没有正确添加,或者由于某种原因从未收到消息一样。

当您在 manifest.json 中声明content_scripts时,默认情况下它会在DOMContentLoadedload事件之间运行,因此如果您在仍在加载的复杂页面上打开弹出窗口,则不会有内容脚本来接收消息。

您可以指定"run_at":"document_start"以使内容脚本在页面仍为空时在"开始"运行,DOM 将只有<html>节点的document.documentElement,不会有<head><body>

请注意,在 manifest.json 中声明的内容脚本始终在每个匹配的页面中运行,因此,如果您的扩展仅在弹出窗口中单击后才需要内容脚本,这将非常非常糟糕,因为你浪费了 99.999% 的时间资源,并且实际上需要广泛的主机权限。在这种情况下,您应该 1) 从 manifest.json 中删除content_scripts,2) 在"权限"中添加activeTab并删除任何广泛的主机权限,例如<all_urls>*://*/*http://*/*,3) 像以前一样使用 executeScript 和 hasListeners。

最新更新