chrome插件实时通信的几种方式

在chrome插件开发中我们知道,background.js是独立于浏览器的,在background.js中主要负责popup与content.js的交互,在某些时候,也许你需要在一个插件的设置页与content进行实时通信,此时你能想到什么样的方式吗?本文是在插件业务通信总结的一篇笔记,希望看完能在实际业务中带来思考和帮助

正文开始...

在插件通信中,我们先从background、popup、content中来一起重温那些常用的通信交互

background.js

chrome.runtime.onMessage.addListener监听content.js发送过来的消息

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

在content.js中,使用chrome.runtime.sendMessage(params),当我们在content.js点击设置按钮时,此时就会打开设置页,此时会触发backrgound.js

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中发送消息

js 复制代码
 document.getElementById("light").onclick = function () {
    console.log("light");
    // changeTheme,向background发送消息
    chrome.runtime.sendMessage({ type: "changeTheme", theme: "light" });
  };

我们会发现backrgound.js中接收到了来自set页面的信息

js 复制代码
// 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实时通信

比如现在有个场景,我在设置页需要设置content页面的主题,而且需要实时修改,那么怎么办呢?

主要利用chrome.tabs.query与chrome.tabs.sendMessage这两个api实现

js 复制代码
  // 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发送过来的消息

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的状态,那该怎么办呢?

其实我们只需要修改一行代码即可

js 复制代码
 function sendMessageToActiveTab(message) {
    // 向所有的tabde
    chrome.tabs.query({}, function (tabs) {
      tabs
        .forEach((v) => {
          chrome.tabs.sendMessage(v.id, message);
        });
    });
  }

缓存

当你在设置页修改状态时,content确实是可以实时变化了,但是,当你刷新,当前的状态的就会改变,所以你需要如何保持当前状态,那么你需要用到插件的缓存功能

在使用缓存功能之前,你需要在permission中添加storage

json 复制代码
{
   "permissions": ["storage"]
}

在插件的设置页面

js 复制代码
  // 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中

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监听发送过来的消息

  • code example

相关推荐
知了学历孙老师1 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
ShineWinsu3 小时前
对于JavaScript:操作元素的解析
开发语言·前端·javascript·面试·web·dom·元素
福兮说4 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json
程序员老赵6 小时前
Docker 部署青龙面板:轻松搭建定时任务管理平台
前端·docker·开源
Swot6 小时前
Asciidoctor 公式数字下标错位问题:原因分析与解决方案
前端
Swot6 小时前
leo-editor 中将 Markdown 内容转成 asciidoc 格式
前端
狒狒AI6 小时前
Remotion / GSAP+Three / HyperFrames / Skia 四栈实测:代码渲染知识视频的选栈方法(附开源技能)
前端·人工智能·aigc
修炼的dance6 小时前
浏览器里导出H.265,8.5秒和55.5秒差在硬件
前端
补码缩写6 小时前
WebCodecs选编码器,探测之后还要验解码和播放
前端
大文说跨境6 小时前
亚马逊多账号管理浏览器怎么选?云登/紫鸟/AdsPower 对比
java·前端·自动化