浏览器跨Tab通信

作者: shaokang 时间: October 15, 2024字数:2407

背景

浏览器跨标签页通信是指在同一个浏览器窗口中的多个标签页之间进行数据交流和信息传递的过程。通常情况下,每个标签页都是一个独立的浏览器上下文,它们之间是相互隔离的,无法直接访问对方的数据或进行通信。

跨标签页通信的目的是允许这些相互隔离的标签页之间进行信息共享和交互。通过跨标签页通信,可以实现数据的共享、状态的同步、消息的传递等功能。

实现方式

1. LocalStorage、SessionStorage

A 标签页将数据存储在 LocalStorage 或 SessionStorage 中,B 标签页可以监听存储事件来获取更新的数据。

// 在 A 标签页中存储数据
localStorage.setItem('sharedData', 'Tab A');

// 在 B 标签页中监听存储事件,并获取更新的数据
window.addEventListener('storage', function (event) {
    if (event.key === 'sharedData') {
        const newData = event.newValue;
        console.log('Received updated data:', newData);
    }
});
// 同时在 B 标签页中更新数据
localStorage.setItem('sharedData', 'Tab B');

2. Broadcast Channel API

Broadcast Channel API 允许不同标签页之间通过一个共同的频道进行通信。A 标签页创建了一个广播通道,B 标签页可以监听该频道来获取消息。

// 在 A 标签页中创建广播通道
const channel = new BroadcastChannel('channelName');

// 在 B 标签页中监听广播通道
const channel = new BroadcastChannel('channelName');
channel.onmessage = function (event) {
    console.log('Received message:', event.data);
};

// 在 A 标签页中发送消息
const channel = new BroadcastChannel('channelName');
channel.postMessage('Hello from Tab A!');

// 在 B 标签页中发送消息
const channel = new BroadcastChannel('channelName');
channel.postMessage('Hello from Tab B!');

3. SharedWorker

SharedWorker 是一种跨标签页共享的 Web Worker,它可以在多个标签页中运行同一个脚本。A 标签页创建了一个 SharedWorker,B 标签页可以连接到该 SharedWorker 来获取消息或执行任务。

// 在 A 标签页中创建 SharedWorker
const worker = new SharedWorker('shared-worker.js');
worker.port.postMessage('Hello from Tab A!');

// 在 B 标签页中连接 SharedWorker
const worker = new SharedWorker('shared-worker.js');
worker.port.onmessage = function (event) {
    console.log('Received message:', event.data);
};

// shared-worker.js 文件
// 监听连接事件
self.onconnect = function (event) {
    const port = event.ports[0];

    // 监听消息事件
    port.onmessage = function (event) {
        const message = event.data;
        console.log('Received message:', message);

        // 发送消息
        port.postMessage('Hello from Worker');
    };

    port.start();
};

4. Service Worker API

Service Worker API 允许在后台运行脚本,独立于主线程和页面。它可以被用来实现跨标签页通信、离线缓存等高级功能。

// 在 A 标签页中注册 Service Worker
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('sw.js');
}

// 在 A 标签页中发送消息
const sw = navigator.serviceWorker.controller;
sw.postMessage('Hello from Tab A!');

// 在 B 标签页中监听消息事件
navigator.serviceWorker.addEventListener('message', function (event) {
    console.log('Received message:', event.data);
});

总结

以上方式都必须在同源页面下,除此之外也可以通过 IndexedDB、服务端 Websocket 等方式。不同域之间则需要通过 postMessage 来实现通信。