localStorage
+ storage
事件localStorage
可以在同一个浏览器的不同标签页之间共享数据。通过监听 storage
事件,可以在一个标签页中监听另一个标签页对 localStorage
的更改。
标签页 A:
// 更新 localStorage 中的值
localStorage.setItem('message', 'Hello from Tab A');
标签页 B:
// 监听 localStorage 的变化
window.addEventListener('storage', (event) => {
if (event.key === 'message') {
console.log('Message from another tab:', event.newValue);
}
});
BroadcastChannel
APIBroadcastChannel
API 提供了一个简单的方式来在同源的不同浏览器上下文(如不同标签页、iframe 或 worker)之间进行通信。
标签页 A:
const channel = new BroadcastChannel('my_channel');
channel.postMessage('Hello from Tab A');
标签页 B:
const channel = new BroadcastChannel('my_channel');
channel.onmessage = (event) => {
console.log('Message from another tab:', event.data);
};
SharedWorker
SharedWorker
可以在同一浏览器中的多个标签页之间共享数据和事件。它在多个标签页之间共享一个 JavaScript 上下文。
shared-worker.js:
// Shared Worker 脚本
self.onconnect = (event) => {
const port = event.ports[0];
port.onmessage = (e) => {
port.postMessage(`Hello ${e.data} from Shared Worker`);
};
};
标签页 A 和 B:
const worker = new SharedWorker('shared-worker.js');
worker.port.postMessage('Tab A');
worker.port.onmessage = (event) => {
console.log(event.data);
};
Service Worker
虽然 Service Worker
主要用于离线缓存和推送通知,但它也可以用作标签页之间的消息中介。
service-worker.js:
self.addEventListener('message', (event) => {
event.waitUntil(
clients.matchAll().then((clients) => {
clients.forEach((client) => client.postMessage(event.data));
})
);
});
标签页 A 和 B:
navigator.serviceWorker.register('/service-worker.js').then((registration) => {
navigator.serviceWorker.ready.then((swRegistration) => {
swRegistration.active.postMessage('Hello from Tab A');
});
navigator.serviceWorker.addEventListener('message', (event) => {
console.log('Message from Service Worker:', event.data);
});
});
IndexedDB
+ 轮询使用 IndexedDB
来存储共享数据,并使用 setInterval
定期检查数据库中的变化。
标签页 A:
const dbRequest = indexedDB.open('myDB', 1);
dbRequest.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(['messages'], 'readwrite');
const store = transaction.objectStore('messages');
store.put({ id: 'latest', message: 'Hello from Tab A' });
};
dbRequest.onupgradeneeded = (event) => {
const db = event.target.result;
db.createObjectStore('messages', { keyPath: 'id' });
};
标签页 B:
setInterval(() => {
const dbRequest = indexedDB.open('myDB', 1);
dbRequest.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(['messages'], 'readonly');
const store = transaction.objectStore('messages');
const getRequest = store.get('latest');
getRequest.onsuccess = () => {
console.log('Message from another tab:', getRequest.result.message);
};
};
}, 1000);
localStorage
+ storage
事件:简单易用,但只能触发变化事件,不能主动发送消息。BroadcastChannel
:现代浏览器支持较好,适合同源的标签页之间通信。SharedWorker
:可以共享 JavaScript 上下文,但需要加载共享 worker 脚本。Service Worker
: 适用于进阶应用场景,可以处理更多复杂任务。IndexedDB
+ 轮询:适用于需要存储大量数据并轮询获取更新的场景,但效率较低。根据具体需求选择合适的方式来实现跨标签页通信。