消息传情:插件组件间的通信密语
在浏览器插件的宇宙中,各个组件如同散落星辰,弹窗(Popup)是闪烁的灯塔,后台服务(Service Worker)是沉默的指挥官,内容脚本(Content Script)则是穿梭在网页中的信使。它们各自为政,却需默契协作。此时,消息传递便成了跨越时空的密语,让组件间的心跳同步共鸣。
通信三重境界:从私语到呐喊
一对一私语(最常用的通信方式)
适用于弹窗与后台,内容脚本与服务的深度对话,通过chrome.runtime.sendMessage来发送信息,使用chrome.runtime.onMessage来接收信息。
发送密信 --- sendMessage的艺术
参数详解
message -- 消息本尊 -- 任意可序列化的对象 -- 携带要传递的数据,是通信的核心内容
options -- 配置之门 -- 可选
callback -- 响应之桥 -- 函数 -- 接收接收方的响应(通过 sendResponse 或 Promise)-- 可选
使用示例
// 发送方:弹窗或内容脚本
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插件开发,手把手教你构建实用功能,开启浏览器扩展创作之旅。

