在之前的 Chrome Extension
开发的初探文章当中,我对 消息传递 的认识还比较浅,最近又双叒叕学到了一点点这方便的新知识,也在一次又一次的功能实践当中也体会到了消息传递在实用当中重要性。所以还是再写一篇关于消息传递的内容,另外个人觉得这个方向非常不错,也推荐给各位。
在 Chrome 扩展开发中,message
通信机制是核心技术之一,它允许扩展的不同组件(如内容脚本、后台脚本、弹出页面、选项页面等)通过发送和接收消息来进行互动和协作。这种通信方式打破了扩展组件之间的孤立状态,使得它们能够像团队一样高效地协同工作,共享数据,触发操作,甚至执行复杂的逻辑处理。
通过 message
通信,内容脚本可以向后台脚本请求数据或执行后台任务,而后台脚本则可以根据接收到的消息作出响应,并将结果传回给内容脚本或其他组件。此外,弹出页面可以通过消息向后台脚本发送用户指令,更新扩展的状态,或与当前网页内容进行交互。
这种机制不仅提高了扩展的灵活性和功能性,还增强了扩展在处理异步任务和用户交互时的响应能力。例如,当用户在弹出页面中点击按钮时,后台脚本可以即时接收消息,执行相关操作,如访问远程 API、更新存储的数据或通知内容脚本在当前页面上进行某些操作。
message
通信机制在 Chrome 扩展开发中扮演了关键角色,使得复杂的扩展能够以模块化的方式构建,每个组件各司其职,又能够通过消息传递无缝协作,实现扩展整体功能的最大化。
在 Chrome 扩展开发中,message
通信有多种常见的应用场景,每种场景都涉及扩展不同组件之间的消息传递。这些场景通常包括内容脚本与后台脚本的通信、弹出页面与后台脚本的交互、扩展各部分之间的广播消息等。以下是一些典型的message
通信场景:
应用示例: 内容脚本检测到网页上的特定元素变化后,向后台脚本发送消息,请求后台脚本抓取或更新数据。内容脚本从后台脚本请求用户的设置数据,获取后根据设置动态修改网页内容。
场景描述: 弹出页面是用户与扩展互动的入口,通常需要根据用户的操作触发后台脚本执行某些任务。由于弹出页面只在被打开时存在,因此需要与持久运行的后台脚本通信来保持状态和执行操作。
应用示例: 用户在弹出页面中点击按钮后,向后台脚本发送消息,后台脚本接收后执行相应的操作,如保存数据或触发通知。弹出页面在加载时请求后台脚本获取当前状态信息,以便显示最新的应用状态或用户数据。
这些场景展示了message
通信机制在 Chrome 扩展开发中的广泛应用,它使得扩展能够有效地管理和协调其不同部分,确保功能的顺畅运行和用户体验的一致性。
Chrome 扩展的 message
通信机制主要包括以下几种情况,每种情况都对应了扩展内部不同组件之间的消息传递方式。这些通信方式确保了扩展的各个部分能够高效协作,实现复杂功能和良好的用户体验。
单向消息传递 是 Chrome 扩展中的一种基本通信方式,它指的是消息从一个组件发送到另一个组件后,不需要立即收到回复或反馈。这种方式适用于简单的通知或触发操作场景,在扩展的各个部分之间传递信息时非常常见。
单向消息传递 是 Chrome 扩展中的一种基本通信方式,它指的是消息从一个组件发送到另一个组件后,不需要立即收到回复或反馈。这种方式适用于简单的通知或触发操作场景,在扩展的各个部分之间传递信息时非常常见。
单向消息传递 的优点:
注意事项: 由于是单向消息传递,发送方无法确认接收方是否成功处理了消息。因此,这种方式更适用于无需确认的简单通信场景。
下面是一个关于 Chrome 扩展中单向消息传递的简单例子,展示了内容脚本向后台脚本发送消息的过程。
内容脚本侦听网页上的按钮点击事件,并在按钮被点击时向后台脚本发送一条消息。
// 侦听页面上按钮的点击事件
document.getElementById('myButton').addEventListener('click', function() {
// 向后台脚本发送消息
chrome.runtime.sendMessage({ action: 'buttonClicked', data: 'Hello from content script' });
});
后台脚本接收内容脚本发送的消息,并处理该消息(例如,记录日志或执行其他操作)。
// 监听来自内容脚本的消息
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message.action === 'buttonClicked') {
// 处理收到的消息
console.log('Received message:', message.data);
// 这里可以执行其他操作,例如更新扩展状态或发送通知
}
});
在这个例子中,当用户点击网页上的按钮时,内容脚本通过 chrome.runtime.sendMessage
方法向后台脚本发送了一条消息。后台脚本接收到消息后,通过 chrome.runtime.onMessage.addListener
监听器处理该消息。
双向长连接通信 是 Chrome 扩展中一种高级的通信机制,它允许扩展的两个组件之间建立持久的连接,并进行持续的双向数据交换。这种方式适用于需要实时更新、持续通信的场景,如内容脚本与后台脚本之间的实时数据同步或状态监控。
双向长连接通信特点
内容脚本通过 chrome.runtime.connect
方法与后台脚本建立连接,并监听连接端口上的消息。
// 与后台脚本建立连接
const port = chrome.runtime.connect({ name: 'content-background' });
// 监听来自后台脚本的消息
port.onMessage.addListener(function(msg) {
console.log('Received message from background:', msg);
// 可以根据后台脚本的消息更新页面或执行操作
});
// 发送消息给后台脚本
port.postMessage({ action: 'init', data: 'Hello from content script' });
后台脚本通过 chrome.runtime.onConnect.addListener
监听内容脚本的连接请求,并在连接建立后监听消息和发送响应。
// 监听内容脚本的连接请求
chrome.runtime.onConnect.addListener(function(port) {
console.log('Connected:', port.name);
// 监听来自内容脚本的消息
port.onMessage.addListener(function(msg) {
console.log('Received message from content script:', msg);
// 根据收到的消息执行操作,并发送回应
if (msg.action === 'init') {
port.postMessage({ response: 'Connection established' });
}
});
// 连接关闭时执行操作
port.onDisconnect.addListener(function() {
console.log('Port disconnected');
});
});
例子的详细解释:
chrome.runtime.connect
方法与后台脚本建立连接,并指定一个连接名称name
,以便区分不同的连接。port
) 进行双向消息传递。port.postMessage
用于发送消息,port.onMessage.addListener
用于接收消息。port.onDisconnect.addListener
监听连接断开事件。跨扩展/应用的消息传递 是指在不同的 Chrome 扩展、应用或网页之间传递消息。这种通信方式允许不同的扩展或应用之间进行数据交换或协作,实现更复杂的功能和集成。以下是跨扩展/应用消息传递的主要方式和应用场景:
这种方式允许一个扩展向另一个扩展发送消息,但前提是这两个扩展都需要声明适当的权限,并且消息传递是通过扩展的 ID 实现的。
跨扩展/应用的消息传递 有两种实现方式,总结为 消息模型
和 连接模型
。这与前两者消息类型有相似的关系。
要向另一个扩展发送消息,您需要知道目标扩展的 ID。可以使用 chrome.runtime.sendMessage
发送消息到指定的扩展。
// 向指定 ID 的扩展发送消息
chrome.runtime.sendMessage('TARGET_EXTENSION_ID', { action: 'someAction', data: 'Hello from extension A' });
目标扩展需要在其后台脚本或其他组件中监听消息,并作出相应的处理。
// 监听来自其他扩展的消息
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message.action === 'someAction') {
console.log('Received message from another extension:', message.data);
// 处理消息
}
});
这种方法适用于建立持久的连接,可以用于跨扩展的持久通信。
扩展 A 通过 chrome.runtime.connect
建立与扩展 B 的连接(前提是扩展 B 允许此连接)。
// 扩展 A 中建立连接
const port = chrome.runtime.connect('TARGET_EXTENSION_ID', { name: 'extensionA-to-B' });
扩展 B 监听来自扩展 A 的连接请求,并处理数据交换。
// 扩展 B 中监听连接
chrome.runtime.onConnect.addListener(function(port) {
console.log('Connected with port name:', port.name);
port.onMessage.addListener(function(message) {
console.log('Received message from extension A:', message);
// 处理消息
});
});
要使跨扩展消息传递功能正常工作,目标扩展需要在其 manifest.json
文件中声明权限。通常需要声明 *://*/*
或特定的 URL 权限,以及 identity
权限。
{
"manifest_version": 3,
"name": "Extension B",
"version": "1.0",
"permissions": [
"identity",
"https://FunTester.com/*" // 指定允许的 URL 或域名
],
"background": {
"service_worker": "background.js"
}
}
注意事项:
页面与内容脚本之间的消息传递 是在 Chrome 扩展中实现网页(页面脚本)与内容脚本之间的数据交换和互动的机制。内容脚本运行在网页的隔离环境中,而页面脚本是网页本身的 JavaScript
代码,两者之间不能直接共享变量或函数。因此,需要使用消息传递机制进行通信。
通过这些机制,Chrome 扩展能够在网页和扩展的不同组件之间实现高效的数据交换和互动,增强用户体验和扩展功能。与 跨扩展/应用的消息传递 类似,也有两种不同风格的 API
。
window.postMessage
是在页面脚本和内容脚本之间传递消息的主要方式。它允许不同的窗口(包括 iframe 和跨域窗口)之间发送消息。具体步骤如下:
内容脚本通过 window.postMessage
向网页中的页面脚本发送消息。
// 向页面脚本发送消息
window.postMessage({ type: 'FROM_CONTENT_SCRIPT', data: 'Hello from content script' }, '*');
页面脚本监听来自内容脚本的消息,并处理这些消息。
// 监听来自内容脚本的消息
window.addEventListener('message', function(event) {
if (event.origin !== 'http://expected-origin.com') {
// 验证消息来源
return;
}
if (event.data.type === 'FROM_CONTENT_SCRIPT') {
console.log('Received message from content script:', event.data.data);
// 处理消息
}
});
这种方式用于内容脚本与背景脚本之间的消息传递,但在页面脚本和内容脚本之间需要依赖内容脚本作为中介。
内容脚本从页面脚本接收消息,并可以通过 chrome.runtime.sendMessage
将其转发给后台脚本。
// 监听来自页面脚本的消息
window.addEventListener('message', function(event) {
if (event.data.type === 'FROM_PAGE_SCRIPT') {
// 处理来自页面脚本的消息
chrome.runtime.sendMessage({ type: 'FROM_CONTENT_SCRIPT', data: event.data.data });
}
});
页面脚本通过 window.postMessage
向内容脚本发送消息。
// 向内容脚本发送消息
window.postMessage({ type: 'FROM_PAGE_SCRIPT', data: 'Hello from page script' }, '*');
后台脚本接收内容脚本转发的消息。
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message.type === 'FROM_CONTENT_SCRIPT') {
console.log('Received message from content script:', message.data);
// 处理消息
}
});
window.postMessage
从页面脚本发送消息到内容脚本。window.addEventListener
监听来自页面脚本的消息。内容脚本可以选择直接处理消息,也可以通过 chrome.runtime.sendMessage
将消息转发到后台脚本。window.postMessage
向页面脚本发送消息。window.addEventListener
监听来自内容脚本的消息。FunTester 原创精华