

在chrome[1]插件开发中我们知道,background.js是独立于浏览器的,在background.js中主要负责popup与content.js的交互,在某些时候,也许你需要在一个插件的设置页与content进行实时通信,此时你能想到什么样的方式吗?本文是在插件业务通信总结的一篇笔记,希望看完能在实际业务中带来思考和帮助
正文开始...
在插件通信中,我们先从background、popup、content中来一起重温那些常用的通信交互
chrome.runtime.onMessage.addListener监听content.js发送过来的消息
// background.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
const { type } = request;
console.log(request)
if (type === "open_set_page") {
// 打开设置页
chrome.runtime.openOptionsPage();
}
})
在content.js中,使用chrome.runtime.sendMessage(params),当我们在content.js点击设置按钮时,此时就会打开设置页,此时会触发backrgound.js
// content.js
const setBtnDom = document.getElementById("set");
setBtnDom.onclick = function () {
// 向background.js传入消息
chrome.runtime.sendMessage({
type: "open_set_page",
});
};
background.js通信我们在content.js中打开了一个设置页,此时如果设置页向与content进行通信,那么该怎么办呢?
我们尝试在设置页向background.js中发送消息
document.getElementById("light").onclick = function () {
console.log("light");
// changeTheme,向background发送消息
chrome.runtime.sendMessage({ type: "changeTheme", theme: "light" });
};

我们会发现backrgound.js中接收到了来自set页面的信息
// background.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
const { type } = request;
// 打开设置页面
if (type == "open_set_page") {
chrome.runtime.openOptionsPage();
}
if (type === "changeTheme") {
console.log(request, "=request");
}
});
比如现在有个场景,我在设置页需要设置content页面的主题,而且需要实时修改,那么怎么办呢?
主要利用chrome.tabs.query与chrome.tabs.sendMessage这两个api实现
// set.js
function sendMessageToActiveTab(message) {
// 获取当前活动标签
chrome.tabs.query({}, function (tabs) {
tabs
.filter((v) => v.active)
.forEach((v) => {
chrome.tabs.sendMessage(v.id, message);
});
});
}
let flag = true;
document.getElementById("dark").onclick = function () {
flag = !flag;
sendMessageToActiveTab({ action: "buttonClicked", theme: flag ? "dark" : "light" });
};
在content.js中我们监听set.js发送过来的消息
const textDom = document.getElementById("text");
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
console.log(sender.id, chrome.runtime.id);
const {theme} = request;
textDom.style.color = theme === 'dark' ? "black": "red"
});
此时你会发现当你在设置点击按钮操作时,当前激活的tab就会实时触发
但是有一个场景,就是我想修改所有的content的状态,那该怎么办呢?
其实我们只需要修改一行代码即可
function sendMessageToActiveTab(message) {
// 向所有的tabde
chrome.tabs.query({}, function (tabs) {
tabs
.forEach((v) => {
chrome.tabs.sendMessage(v.id, message);
});
});
}
当你在设置页修改状态时,content确实是可以实时变化了,但是,当你刷新,当前的状态的就会改变,所以你需要如何保持当前状态,那么你需要用到插件的缓存功能
在使用缓存功能之前,你需要在permission中添加storage
{
"permissions": ["storage"]
}
在插件的设置页面
// set.js
let flag = true;
document.getElementById("dark").onclick = function () {
flag = !flag;
// port.postMessage({ type: "changeTheme", theme: "dark" });
const theme = flag ? "dark" : "light";
sendMessageToActiveTab({
action: "buttonClicked",
theme,
});
chrome.storage.local.set({ theme });
};
在content.js中
// content.js
chrome.storage.local.get("theme", function (result) {
console.log(result, "result");
const { theme = "" } = result || { theme: "" };
if (theme === "dark") {
textDom.style.color = "black";
} else {
textDom.style.color = "red";
}
});
当你在chrome设置页设置缓存时,你在content重新刷新,那么就可以正常的获取缓存了。
content.js与background.js的通信,或者是popup与content的通信,借助chrome.runtime.sendMessage实现content.js实时通信,我们是借助先查询所有的tabs,chrome.tabs.query({}, callback),然后再向所有的tabs发送消息chrome.tabs.sendMessage(id, data),最后在content.js中chrome.runtime.onMessage监听发送过来的消息[1]chrome: https://developer.chrome.com/docs/extensions/whatsnew/
[2]code example: https://github.com/maicFir/lessonNote/tree/master/chrome-plugin/06-demo