消息传情:插件组件间的通信密语

在浏览器插件的宇宙中,各个组件如同散落星辰,弹窗(Popup)是闪烁的灯塔,后台服务(Service Worker)是沉默的指挥官,内容脚本(Content Script)则是穿梭在网页中的信使。它们各自为政,却需默契协作。此时,消息传递便成了跨越时空的密语,让组件间的心跳同步共鸣。

通信三重境界:从私语到呐喊

一对一私语(最常用的通信方式)

适用于弹窗与后台,内容脚本与服务的深度对话,通过chrome.runtime.sendMessage来发送信息,使用chrome.runtime.onMessage来接收信息。

发送密信 --- sendMessage的艺术

参数详解

message -- 消息本尊 -- 任意可序列化的对象 -- 携带要传递的数据,是通信的核心内容

options -- 配置之门 -- 可选

callback -- 响应之桥 -- 函数 -- 接收接收方的响应(通过 sendResponsePromise)-- 可选

使用示例

// 发送方:弹窗或内容脚本
chrome.runtime.sendMessage({
  type: "REQUEST",        // 消息类型(建议枚举)
  payload: { data: 42 },  // 有效载荷(可为任意结构)
  source: "popup"         // 可选来源标识
});

倾听密语 --- onMessage的守望

参数详情

request -- 发送方消息的对象

sender -- 发送者元信息 (tab frame url)

sendResponse -- 响应函数

使用示例

// 接收方:Service Worker 或 Content Script
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === "REQUEST") {
    console.log("收到来自", sender.tab?.url || sender.url, "的请求");
    sendResponse({ status: "SUCCESS", result: request.payload.data * 2 });
  }
  // 若需异步处理,返回 true 保持通道开放
  return true;
});

进阶技巧

//定义messageType.js 统一管理通信协议
export const TYPES = {
  CHANGE_COLOR: "CHANGE_COLOR",
  FETCH_DATA: "FETCH_DATA",
  ERROR: "ERROR"
};

//错误处理
chrome.runtime.sendMessage(message, (response) => {
  if (chrome.runtime.lastError) {
    console.error("通信失联!", chrome.runtime.lastError);
  } else if (response?.status === "SUCCESS") {
    console.log("响应成功", response.result);
  }
});

一对多广播

适用于广播全局状态变更(如用户登录),通过chrome.runtime.connect发送,chrome.runtime.onConnect接收。

使用示例

// 后台服务:创建监听通道
const port = chrome.runtime.connect({ name: "statusChannel" });
port.onMessage.addListener((msg) => {
  if (msg.type === "STATUS_UPDATE") {
    console.log("全局状态更新为:", msg.payload);
  }
});

// 其他组件:发送广播
chrome.runtime.connect().postMessage({ 
  type: "STATUS_UPDATE", 
  payload: "online" 
});

跨域传输

适用于插件与网页,跨域iframe的非常规通信,通过window.postMessage借道

使用示例

// Content Script:监听网页消息
window.addEventListener("message", (event) => {
  if (event.origin !== "https://trusted-site.com") return;
  if (event.data.type === "PLUGIN_REQUEST") {
    chrome.runtime.sendMessage({ 
      type: "WEB_REQUEST", 
      payload: event.data.payload 
    });
  }
});

// 网页脚本:主动通信
window.postMessage({ 
  type: "PLUGIN_REQUEST", 
  payload: "需要插件处理的数据" 
}, "https://your-extension.com");

实践案例---拖拽图片直接下载

有时候,你会不会觉得在网页上下载图片麻烦了点🤔,你们能不能把这个过程简化一下呢,比如我点击图片拖动一下就自动下载。

{
  "manifest_version": 3,
  "name": "拖拽图片自动下载",
  "version": "1.0",
  "description": "在网页中拖动图片时自动下载图片",
  "permissions": [
    "downloads",
    "activeTab"
  ],
  "content_scripts": [
    {
      "matches": [
        "<all_urls>"
      ],
      "js": [
        "content.js"
      ]
    }
  ],
  "background": {
    "service_worker": "background.js"
  }
}
// content.js
// 监听图片的拖动开始事件
document.addEventListener("dragstart", (event) => {
  const target = event.target;

  // 确保是图片
  if (target.tagName.toLowerCase() === "img") {
    const imageUrl = target.src;

    // 向后台发送图片地址,触发下载
    chrome.runtime.sendMessage({
      type: "downloadImage",
      url: imageUrl
    });
  }
});

//background.js
function getFileNameL() {
    return `image_${Date.now()}.png`;
  }
  
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.type === "downloadImage") {
      const imageUrl = message.url;
      const name = getFileNameL()
      // 使用 chrome.downloads.download 下载图片
      chrome.downloads.download({
        url: imageUrl,
        filename: name,
        saveAs: true // 弹出保存对话框
      });
    }
  });

成果展示

从零探索Chrome插件开发,手把手教你构建实用功能,开启浏览器扩展创作之旅。

全部评论
求链接
点赞 回复 分享
发布于 08-09 20:26 江苏
点赞 回复 分享
发布于 08-09 20:22 江苏

相关推荐

08-08 01:02
门头沟学院 Java
点赞 评论 收藏
分享
评论
4
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务