1.Broadcast Channel API
定义
Broadcast Channel API 是一种浏览器提供的 API,用于在同一来源(同一域名和端口)的不同浏览器上下文(如不同标签页、iframe、web workers)之间传递消息。它允许这些上下文之间通过一个共享的频道来广播消息。
特点
- 跨标签页/iframe通信:允许同源的多个标签页、iframe 间传递消息。
- 异步消息传递:消息在不同上下文间是异步的,基于事件监听来处理消息的接收。
- 不依赖前端框架:原生的浏览器 API,可以在任何前端项目中使用,不与具体的框架绑定。
- 作用范围:消息广播作用于所有连接到该频道的上下文,所有监听该频道的上下文都会收到消息。
示例代码
// 创建或连接到一个广播频道
const bc = new BroadcastChannel('test_channel');
// 发送消息
bc.postMessage('这是一条测试消息。');
// 监听消息
bc.onmessage = (event) => {
console.log('接收到消息:', event);
};
// 关闭频道
bc.close();
2.window.postMessage
定义
window.postMessage 是浏览器提供的用于跨窗口、跨 iframe 的通信 API。它允许在不同源或同源的窗口、iframe 之间发送消息,消息会发送到一个特定的窗口(单播模式)。
语法
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
- 类型: Window 对象
- 含义: 这是消息的接收窗口对象,可以是:
• 一个 iframe 的 contentWindow 对象。
• 用 window.open() 打开的新窗口。
message
- 类型: 任意数据类型(字符串、对象、数组等)
- 含义: 要发送的消息内容
targetOrigin
• 类型: 字符串
- 含义: 指定消息接收窗口的源(origin),包括协议、域名和端口号。这个参数的作用是确保消息只被发送到指定的可信窗口,防止不安全的跨域消息接收。
- 格式: targetOrigin 必须匹配接收窗口的 origin(即协议 + 域名 + 端口),否则消息将不会被接收。
- 特例: 如果设置为 "*", 消息将发送到任意源窗口。
transfer(可选)
- 类型: 可选参数
- 含义: 是一串和 message 同时传递的
Transferable
对象。这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
工作原理
- 发送窗口使用 postMessage 将消息发送给接收窗口,指定的 targetOrigin 是为了确保消息只能被发送到特定的域名或来源的窗口,避免不安全的跨域通信。
- 接收窗口需要通过 window.addEventListener("message", ...) 事件监听来接收消息,并通过 event.origin 验证消息的来源是否是可信的。
示例代码
假设我们有一个父页面和一个嵌入的 iframe 页面,父页面向 iframe 发送消息,iframe 接收并处理该消息:
父页面代码:
const iframeWindow = document.getElementById("myIframe").contentWindow;
// 发送消息到 iframe,并且只允许 https://example.com 接收消息
iframeWindow.postMessage({ value: "new content" }, "https://example.com");
iframe 页面代码:
window.addEventListener("message", (event) => {
// 验证消息来源
if (event.origin === "https://parent-website.com") {
console.log("接收到数据:", event.data);
// 根据消息内容执行操作
}
});
3.全局事件总线
定义
全局事件总线是前端框架(如 Vue、React)中用于组件之间通信的模式。通常它通过发布/订阅模式在页面内不同组件之间传递事件和数据
特点
- 局限于单个应用实例:全局事件总线一般只在单个页面或单个 Vue/React 实例内有效,不能跨页面或跨 iframe 进行通信。
- 同步或异步事件传递:事件总线中的事件可以是同步触发,也可以通过事件队列异步触发,基于框架的实现机制。
- 与框架强绑定:通常全局事件总线是由框架提供或封装的,与具体框架的生态强相关。
- 作用范围:作用范围通常是整个应用内的所有组件(Vue 中的 $emit 和 $on 等),局限于应用的生命周期内。
示例代码 (Vue)
// 定义事件总线
const EventBus = new Vue();
// 组件A: 发送事件
EventBus.$emit('eventName', data);
// 组件B: 监听事件
EventBus.$on('eventName', (data) => {
console.log('接收信息:', data);
});
4.对比
特性 | Broadcast Channel API | postMessage | 全局事件总线 |
---|---|---|---|
通信对象 | 同源的多个页面、标签页、iframe | 跨源或同源的窗口、iframe | 应用内部的不同组件 |
消息传递方式 | 广播模式,所有在同一个频道中的页面都会接收消息 | 单播模式,发送消息给特定目标窗口 | 全局的事件处理器,任何监听者都能接收 |
同源限制 | 是(只能同源) | 否(可以跨源) | 仅限于单个应用内 |
适用场景 | 同源的多个标签页状态同步、广播消息 | 浏览器环境中 | 同一个应用中不同组件间的消息传递 |
应用范围 | 浏览器环境中 | 依赖前端框架的事件机制 | 前端框架中,组件内部 |
5.总结
- Broadcast Channel API:适合 同源下 多个页面、标签页的 广播通信,使用场景主要是多个页面之间共享信息,比如同步状态或广播事件。
- postMessage:适合 跨源或同源 的 单播通信,主要用于父子窗口、iframe 之间的消息传递,安全性高,且支持跨域。
- 全局事件总线:适用于 同一应用内部 的组件间通信,尤其是在前端框架中没有父子关系的组件之间传递数据。