前端跨页面通信方式
文章类型:实战
发布者:hp
发布时间:2026-07-11
Web应用中,经常需要在不同的浏览器标签页或窗口之间进行数据通信。本文将介绍所有主流的跨页面通信方式,包括原理、适用场景和完整代码示例。
| 方式 | 同源限制 | 实时性 | 数据大小 | 兼容性 | 适用场景 |
|---|---|---|---|---|---|
| BroadcastChannel | 同源 | 实时 | 无限制 | 现代浏览器 | 同源多标签通信 |
| LocalStorage + storage事件 | 同源 | 实时 | 5-10MB | 所有浏览器 | 同源多标签通信 |
| SharedWorker | 同源 | 实时 | 无限制 | 现代浏览器 | 复杂状态共享 |
| postMessage | 跨域 | 实时 | 无限制 | 所有浏览器 | 跨域iframe通信 |
| WebSocket | 跨域 | 实时 | 无限制 | 现代浏览器 | 服务器中转 |
| IndexedDB | 同源 | 轮询 | GB级 | 现代浏览器 | 大数据共享 |
| Cookie | 同域 | 轮询 | 4KB | 所有浏览器 | 简单数据共享 |
| Service Worker | 同源 | 实时 | 无限制 | 现代浏览器 | 离线通信 |
BroadcastChannel是专门为跨标签页通信设计的API,使用简单、性能好、实时性强。
优点
// 页面A - 创建频道并发送消息
const channel = new BroadcastChannel('my_channel');
// 发送消息
channel.postMessage('Hello from Page A');
channel.postMessage({ type: 'user_login', userId: 123 });
// 监听消息
channel.onmessage = (event) => {
console.log('收到消息:', event.data);
};
// 关闭频道
channel.close();
// 页面B - 监听同一频道
const channel = new BroadcastChannel('my_channel');
channel.onmessage = (event) => {
console.log('Page B收到消息:', event.data);
// 可以回复消息
channel.postMessage('Message received by Page B');
};// auth.js - 认证模块
class AuthManager {
constructor() {
this.channel = new BroadcastChannel('auth_channel');
this.setupListener();
}
// 监听其他标签页的认证事件
setupListener() {
this.channel.onmessage = (event) => {
const { type, data } = event.data;
switch(type) {
case 'LOGIN':
this.handleRemoteLogin(data);
break;
case 'LOGOUT':
this.handleRemoteLogout();
break;
case 'TOKEN_REFRESH':
this.handleTokenRefresh(data);
break;
}
};
}
// 登录
login(user, token) {
// 保存到本地
localStorage.setItem('user', JSON.stringify(user));
localStorage.setItem('token', token);
// 通知其他标签页
this.channel.postMessage({
type: 'LOGIN',
data: { user, token }
});
console.log('登录成功,已通知其他标签页');
}
// 登出
logout() {
localStorage.removeItem('user');
localStorage.removeItem('token');
// 通知其他标签页
this.channel.postMessage({ type: 'LOGOUT' });
// 跳转到登录页
window.location.href = '/login';
}
// 处理远程登录
handleRemoteLogin(data) {
console.log('其他标签页已登录,同步状态');
localStorage.setItem('user', JSON.stringify(data.user));
localStorage.setItem('token', data.token);
// 更新UI
this.updateUI(data.user);
}
// 处理远程登出
handleRemoteLogout() {
console.log('其他标签页已登出,同步登出');
localStorage.removeItem('user');
localStorage.removeItem('token');
window.location.href = '/login';
}
// 刷新Token
refreshToken(newToken) {
localStorage.setItem('token', newToken);
this.channel.postMessage({
type: 'TOKEN_REFRESH',
data: { token: newToken }
});
}
handleTokenRefresh(data) {
localStorage.setItem('token', data.token);
console.log('Token已同步刷新');
}
updateUI(user) {
// 更新页面UI
document.getElementById('username').textContent = user.name;
document.getElementById('login-btn').style.display = 'none';
document.getElementById('logout-btn').style.display = 'block';
}
}
// 使用
const authManager = new AuthManager();
// 登录按钮
document.getElementById('login-btn').addEventListener('click', () => {
// 假设登录成功
const user = { id: 1, name: '张三', email: 'zhangsan@example.com' };
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
authManager.login(user, token);
});
// 登出按钮
document.getElementById('logout-btn').addEventListener('click', () => {
authManager.logout();
});// cart.js - 购物车同步
class CartSync {
constructor() {
this.channel = new BroadcastChannel('cart_channel');
this.cart = this.loadCart();
this.setupListener();
}
loadCart() {
const cart = localStorage.getItem('cart');
return cart ? JSON.parse(cart) : [];
}
setupListener() {
this.channel.onmessage = (event) => {
const { action, data } = event.data;
switch(action) {
case 'ADD_ITEM':
this.handleRemoteAdd(data);
break;
case 'REMOVE_ITEM':
this.handleRemoteRemove(data);
break;
case 'UPDATE_QUANTITY':
this.handleRemoteUpdate(data);
break;
case 'CLEAR_CART':
this.handleRemoteClear();
break;
}
};
}
// 添加商品
addItem(product, quantity = 1) {
const existingItem = this.cart.find(item => item.id === product.id);
if (existingItem) {
existingItem.quantity += quantity;
} else {
this.cart.push({ ...product, quantity });
}
this.saveCart();
this.notifyOtherTabs('ADD_ITEM', { product, quantity });
this.updateUI();
}
// 移除商品
removeItem(productId) {
this.cart = this.cart.filter(item => item.id !== productId);
this.saveCart();
this.notifyOtherTabs('REMOVE_ITEM', { productId });
this.updateUI();
}
// 更新数量
updateQuantity(productId, quantity) {
const item = this.cart.find(item => item.id === productId);
if (item) {
item.quantity = quantity;
this.saveCart();
this.notifyOtherTabs('UPDATE_QUANTITY', { productId, quantity });
this.updateUI();
}
}
// 清空购物车
clearCart() {
this.cart = [];
this.saveCart();
this.notifyOtherTabs('CLEAR_CART', {});
this.updateUI();
}
// 通知其他标签页
notifyOtherTabs(action, data) {
this.channel.postMessage({ action, data });
}
// 处理远程操作
handleRemoteAdd(data) {
console.log('其他标签页添加了商品');
this.cart = this.loadCart();
this.updateUI();
}
handleRemoteRemove(data) {
console.log('其他标签页移除了商品');
this.cart = this.loadCart();
this.updateUI();
}
handleRemoteUpdate(data) {
console.log('其他标签页更新了数量');
this.cart = this.loadCart();
this.updateUI();
}
handleRemoteClear() {
console.log('其他标签页清空了购物车');
this.cart = [];
this.updateUI();
}
saveCart() {
localStorage.setItem('cart', JSON.stringify(this.cart));
}
updateUI() {
// 更新购物车图标数量
const totalItems = this.cart.reduce((sum, item) => sum + item.quantity, 0);
document.getElementById('cart-count').textContent = totalItems;
// 更新购物车列表
this.renderCartList();
}
renderCartList() {
const cartElement = document.getElementById('cart-list');
cartElement.innerHTML = this.cart.map(item => `
${item.name}
数量: ${item.quantity}
价格: ${item.price * item.quantity}元
删除
`).join('');
}
}
// 使用
const cartSync = new CartSync();// 检测浏览器是否支持
if ('BroadcastChannel' in window) {
const channel = new BroadcastChannel('my_channel');
// 使用BroadcastChannel
} else {
console.log('浏览器不支持BroadcastChannel,使用替代方案');
// 使用LocalStorage + storage事件
}利用localStorage的storage事件实现跨标签页通信,兼容性最好的方案。
优点
// 当localStorage发生变化时,其他标签页会触发storage事件
// 注意:当前标签页不会触发自己的storage事件
// 页面A - 发送消息
localStorage.setItem('message', JSON.stringify({
type: 'notification',
content: 'Hello',
timestamp: Date.now()
}));
// 页面B - 监听消息
window.addEventListener('storage', (event) => {
if (event.key === 'message') {
const message = JSON.parse(event.newValue);
console.log('收到消息:', message);
}
});// StorageChannel.js - 基于localStorage的通信频道
class StorageChannel {
constructor(channelName) {
this.channelName = channelName;
this.listeners = [];
this.init();
}
init() {
window.addEventListener('storage', (event) => {
if (event.key === this.channelName && event.newValue) {
try {
const data = JSON.parse(event.newValue);
this.listeners.forEach(listener => listener(data));
} catch (e) {
console.error('解析消息失败:', e);
}
}
});
}
// 发送消息
postMessage(data) {
const message = {
data: data,
timestamp: Date.now(),
sender: this.getPageId()
};
localStorage.setItem(this.channelName, JSON.stringify(message));
// 立即删除,避免存储空间占用
// 同时确保每次发送都会触发storage事件
setTimeout(() => {
localStorage.removeItem(this.channelName);
}, 50);
}
// 监听消息
onmessage(callback) {
this.listeners.push(callback);
}
// 移除监听
removeListener(callback) {
this.listeners = this.listeners.filter(l => l !== callback);
}
// 生成页面ID
getPageId() {
if (!this._pageId) {
this._pageId = Math.random().toString(36).substr(2, 9);
}
return this._pageId;
}
// 关闭频道
close() {
this.listeners = [];
}
}
// 使用示例
const channel = new StorageChannel('my_channel');
// 发送消息
channel.postMessage({ type: 'hello', content: 'Hello World' });
// 监听消息
channel.onmessage((data) => {
console.log('收到消息:', data);
});// theme.js - 主题同步
class ThemeSync {
constructor() {
this.channel = new StorageChannel('theme_channel');
this.currentTheme = this.loadTheme();
this.setupListener();
this.applyTheme(this.currentTheme);
}
loadTheme() {
return localStorage.getItem('theme') || 'light';
}
setupListener() {
this.channel.onmessage((message) => {
if (message.type === 'THEME_CHANGE') {
this.applyTheme(message.theme);
}
});
}
// 切换主题
switchTheme(theme) {
this.currentTheme = theme;
localStorage.setItem('theme', theme);
this.applyTheme(theme);
// 通知其他标签页
this.channel.postMessage({
type: 'THEME_CHANGE',
theme: theme
});
}
// 应用主题
applyTheme(theme) {
document.body.className = `theme-${theme}`;
console.log(`已切换到${theme}主题`);
}
}
// 使用
const themeSync = new ThemeSync();
// 主题切换按钮
document.getElementById('theme-toggle').addEventListener('click', () => {
const newTheme = themeSync.currentTheme === 'light' ? 'dark' : 'light';
themeSync.switchTheme(newTheme);
});// notification.js - 跨标签页通知
class NotificationSync {
constructor() {
this.channel = new StorageChannel('notification_channel');
this.setupListener();
}
setupListener() {
this.channel.onmessage((message) => {
if (message.type === 'NEW_NOTIFICATION') {
this.showNotification(message.data);
}
});
}
// 发送通知到所有标签页
broadcast(notification) {
this.channel.postMessage({
type: 'NEW_NOTIFICATION',
data: notification
});
// 也在当前页面显示
this.showNotification(notification);
}
// 显示通知
showNotification(notification) {
// 浏览器通知
if ('Notification' in window && Notification.permission === 'granted') {
new Notification(notification.title, {
body: notification.body,
icon: notification.icon
});
}
// 页面内通知
const notificationElement = document.createElement('div');
notificationElement.className = 'notification';
notificationElement.innerHTML = `
${notification.title}
${notification.body}
`;
document.body.appendChild(notificationElement);
// 3秒后自动消失
setTimeout(() => {
notificationElement.remove();
}, 3000);
}
}
// 使用
const notificationSync = new NotificationSync();
// 收到新消息时
function onNewMessage(message) {
notificationSync.broadcast({
title: '新消息',
body: `来自${message.sender}: ${message.content}`,
icon: '/icon.png'
});
}SharedWorker是运行在后台的脚本,可以被多个页面共享,适合复杂的状态管理和通信。
优点
// shared-worker.js - Worker脚本
const connections = [];
self.addEventListener('connect', (event) => {
const port = event.ports[0];
connections.push(port);
console.log('新连接,当前连接数:', connections.length);
port.onmessage = (e) => {
console.log('收到消息:', e.data);
// 广播给所有连接的页面
connections.forEach(p => {
if (p !== port) { // 不发给自己
p.postMessage(e.data);
}
});
};
port.start();
});
// 页面A - 连接Worker
const worker = new SharedWorker('shared-worker.js');
worker.port.onmessage = (event) => {
console.log('收到消息:', event.data);
};
worker.port.postMessage('Hello from Page A');
// 页面B - 连接同一个Worker
const worker = new SharedWorker('shared-worker.js');
worker.port.onmessage = (event) => {
console.log('收到消息:', event.data);
};
worker.port.postMessage('Hello from Page B');// online-users-worker.js
let onlineUsers = new Set();
self.addEventListener('connect', (event) => {
const port = event.ports[0];
let userId = null;
port.onmessage = (e) => {
const { type, data } = e.data;
switch(type) {
case 'USER_ONLINE':
userId = data.userId;
onlineUsers.add(userId);
broadcastUserList();
break;
case 'USER_OFFLINE':
onlineUsers.delete(data.userId);
broadcastUserList();
break;
case 'GET_USERS':
port.postMessage({
type: 'USER_LIST',
users: Array.from(onlineUsers)
});
break;
}
};
// 连接断开时移除用户
port.addEventListener('close', () => {
if (userId) {
onlineUsers.delete(userId);
broadcastUserList();
}
});
port.start();
});
function broadcastUserList() {
const message = {
type: 'USER_LIST',
users: Array.from(onlineUsers)
};
// 这里需要维护port列表来广播
// 简化示例,实际需要存储所有port
}
// 页面使用
class OnlineUserManager {
constructor(userId) {
this.userId = userId;
this.worker = new SharedWorker('online-users-worker.js');
this.setupListener();
this.goOnline();
}
setupListener() {
this.worker.port.onmessage = (event) => {
const { type, users } = event.data;
if (type === 'USER_LIST') {
this.updateUserList(users);
}
};
}
goOnline() {
this.worker.port.postMessage({
type: 'USER_ONLINE',
data: { userId: this.userId }
});
}
goOffline() {
this.worker.port.postMessage({
type: 'USER_OFFLINE',
data: { userId: this.userId }
});
}
updateUserList(users) {
console.log('在线用户:', users);
const userListEl = document.getElementById('online-users');
userListEl.innerHTML = users.map(id =>
`用户${id}`
).join('');
}
}
// 使用
const userManager = new OnlineUserManager(123);
// 页面关闭前
window.addEventListener('beforeunload', () => {
userManager.goOffline();
});window.postMessage可以安全地实现跨域通信,主要用于iframe和window.open打开的窗口。
优点
// 父页面
const iframe = document.getElementById('myIframe');
// 发送消息给iframe
iframe.contentWindow.postMessage({
type: 'INIT',
data: { userId: 123 }
}, 'https://child-domain.com');
// 监听iframe的消息
window.addEventListener('message', (event) => {
// 验证来源
if (event.origin !== 'https://child-domain.com') {
return;
}
console.log('收到iframe消息:', event.data);
if (event.data.type === 'REQUEST_DATA') {
// 响应iframe的请求
event.source.postMessage({
type: 'RESPONSE_DATA',
data: { name: '张三' }
}, event.origin);
}
});
// iframe页面(子页面)
// 发送消息给父页面
window.parent.postMessage({
type: 'READY',
data: { loaded: true }
}, 'https://parent-domain.com');
// 监听父页面的消息
window.addEventListener('message', (event) => {
// 验证来源
if (event.origin !== 'https://parent-domain.com') {
return;
}
console.log('收到父页面消息:', event.data);
if (event.data.type === 'INIT') {
const userId = event.data.data.userId;
console.log('用户ID:', userId);
}
});// 父窗口
const childWindow = window.open('https://example.com/child.html', '_blank');
// 等待子窗口加载完成
setTimeout(() => {
childWindow.postMessage({
type: 'GREETING',
message: 'Hello Child'
}, 'https://example.com');
}, 1000);
// 监听子窗口消息
window.addEventListener('message', (event) => {
if (event.origin !== 'https://example.com') return;
console.log('子窗口说:', event.data);
});
// 子窗口
// 通知父窗口已加载
window.opener.postMessage({
type: 'LOADED',
message: 'Child window loaded'
}, '*');
// 监听父窗口消息
window.addEventListener('message', (event) => {
console.log('父窗口说:', event.data);
});// 主站点 - 嵌入登录iframe
function setupLoginIframe() {
const iframe = document.getElementById('login-iframe');
window.addEventListener('message', (event) => {
// 验证来源
if (event.origin !== 'https://auth.example.com') {
return;
}
const { type, data } = event.data;
switch(type) {
case 'LOGIN_SUCCESS':
handleLoginSuccess(data.token, data.user);
break;
case 'LOGIN_FAILED':
handleLoginFailed(data.error);
break;
}
});
}
function handleLoginSuccess(token, user) {
localStorage.setItem('token', token);
localStorage.setItem('user', JSON.stringify(user));
// 关闭登录iframe
document.getElementById('login-iframe').style.display = 'none';
// 更新UI
console.log('登录成功:', user);
}
// 登录站点(iframe内)
function submitLogin(username, password) {
// 执行登录逻辑
fetch('/api/login', {
method: 'POST',
body: JSON.stringify({ username, password })
})
.then(res => res.json())
.then(data => {
if (data.success) {
// 通知父页面登录成功
window.parent.postMessage({
type: 'LOGIN_SUCCESS',
data: {
token: data.token,
user: data.user
}
}, 'https://main.example.com');
} else {
window.parent.postMessage({
type: 'LOGIN_FAILED',
data: { error: data.message }
}, 'https://main.example.com');
}
});
}通过WebSocket服务器中转消息,适合需要服务器参与的场景,如实时聊天、协同编辑等。
// WebSocket通信封装
class WebSocketChannel {
constructor(url, userId) {
this.url = url;
this.userId = userId;
this.ws = null;
this.listeners = [];
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log('WebSocket连接成功');
// 注册用户
this.send({
type: 'REGISTER',
userId: this.userId
});
};
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.listeners.forEach(listener => listener(message));
};
this.ws.onerror = (error) => {
console.error('WebSocket错误:', error);
};
this.ws.onclose = () => {
console.log('WebSocket连接关闭,3秒后重连');
setTimeout(() => this.connect(), 3000);
};
}
send(message) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(message));
}
}
onMessage(callback) {
this.listeners.push(callback);
}
broadcast(data) {
this.send({
type: 'BROADCAST',
data: data,
sender: this.userId
});
}
close() {
this.ws.close();
}
}
// 使用
const channel = new WebSocketChannel('ws://localhost:8080', 'user123');
channel.onMessage((message) => {
console.log('收到消息:', message);
});
channel.broadcast({ text: 'Hello everyone!' });// server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
// 存储所有连接的客户端
const clients = new Map();
wss.on('connection', (ws) => {
let userId = null;
ws.on('message', (data) => {
const message = JSON.parse(data);
switch(message.type) {
case 'REGISTER':
userId = message.userId;
clients.set(userId, ws);
console.log(`用户${userId}已连接,当前在线${clients.size}人`);
break;
case 'BROADCAST':
// 广播给所有客户端
broadcast(message, userId);
break;
case 'PRIVATE':
// 私聊
sendPrivate(message.to, message.data);
break;
}
});
ws.on('close', () => {
if (userId) {
clients.delete(userId);
console.log(`用户${userId}已断开`);
}
});
});
// 广播消息
function broadcast(message, senderUserId) {
clients.forEach((client, userId) => {
if (client.readyState === WebSocket.OPEN && userId !== senderUserId) {
client.send(JSON.stringify(message));
}
});
}
// 发送私聊消息
function sendPrivate(userId, data) {
const client = clients.get(userId);
if (client && client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'PRIVATE',
data: data
}));
}
}
console.log('WebSocket服务器运行在端口8080');// collaborative-editor.js
class CollaborativeEditor {
constructor(docId, userId) {
this.docId = docId;
this.userId = userId;
this.channel = new WebSocketChannel('ws://localhost:8080', userId);
this.editor = document.getElementById('editor');
this.setupListener();
this.bindEvents();
}
setupListener() {
this.channel.onMessage((message) => {
if (message.type === 'TEXT_CHANGE' && message.docId === this.docId) {
this.applyRemoteChange(message.data);
}
});
}
bindEvents() {
let timeout;
this.editor.addEventListener('input', () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
this.sendChange();
}, 300);
});
}
sendChange() {
const content = this.editor.value;
this.channel.send({
type: 'TEXT_CHANGE',
docId: this.docId,
data: {
content: content,
cursor: this.editor.selectionStart
}
});
}
applyRemoteChange(data) {
const currentCursor = this.editor.selectionStart;
this.editor.value = data.content;
// 保持光标位置
this.editor.setSelectionRange(currentCursor, currentCursor);
}
}
// 使用
const editor = new CollaborativeEditor('doc123', 'user456');// 使用IndexedDB + 轮询
class IndexedDBChannel {
constructor(dbName) {
this.dbName = dbName;
this.db = null;
this.init();
}
async init() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, 1);
request.onerror = () => reject(request.error);
request.onsuccess = () => {
this.db = request.result;
resolve();
};
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains('messages')) {
db.createObjectStore('messages', { keyPath: 'id', autoIncrement: true });
}
};
});
}
async postMessage(data) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['messages'], 'readwrite');
const store = transaction.objectStore('messages');
const message = {
data: data,
timestamp: Date.now()
};
const request = store.add(message);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
async getMessages(since) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['messages'], 'readonly');
const store = transaction.objectStore('messages');
const request = store.getAll();
request.onsuccess = () => {
const messages = request.result.filter(m => m.timestamp > since);
resolve(messages);
};
request.onerror = () => reject(request.error);
});
}
startPolling(callback) {
let lastCheck = Date.now();
setInterval(async () => {
const messages = await this.getMessages(lastCheck);
messages.forEach(msg => callback(msg.data));
lastCheck = Date.now();
}, 1000);
}
}// 简单的Cookie通信(不推荐,仅作了解)
class CookieChannel {
constructor(channelName) {
this.channelName = channelName;
}
postMessage(data) {
const message = JSON.stringify({
data: data,
timestamp: Date.now()
});
document.cookie = `${this.channelName}=${encodeURIComponent(message)}; path=/`;
}
getMessage() {
const cookies = document.cookie.split('; ');
const cookie = cookies.find(c => c.startsWith(this.channelName + '='));
if (cookie) {
const value = decodeURIComponent(cookie.split('=')[1]);
return JSON.parse(value);
}
return null;
}
startPolling(callback) {
let lastTimestamp = 0;
setInterval(() => {
const message = this.getMessage();
if (message && message.timestamp > lastTimestamp) {
callback(message.data);
lastTimestamp = message.timestamp;
}
}, 500);
}
}// sw.js - Service Worker
const clients = [];
self.addEventListener('message', (event) => {
const { type, data } = event.data;
if (type === 'BROADCAST') {
// 发送给所有客户端
self.clients.matchAll().then(clientList => {
clientList.forEach(client => {
client.postMessage({
type: 'MESSAGE',
data: data
});
});
});
}
});
// 页面中使用
navigator.serviceWorker.register('/sw.js');
navigator.serviceWorker.ready.then(registration => {
// 发送消息
registration.active.postMessage({
type: 'BROADCAST',
data: { text: 'Hello' }
});
// 接收消息
navigator.serviceWorker.addEventListener('message', (event) => {
console.log('收到消息:', event.data);
});
});// 统一的通信接口
class CrossPageChannel {
constructor(channelName) {
this.channelName = channelName;
this.channel = this.createChannel();
}
createChannel() {
// 优先使用BroadcastChannel
if ('BroadcastChannel' in window) {
console.log('使用BroadcastChannel');
return new BroadcastChannelAdapter(this.channelName);
}
// 降级到LocalStorage
else {
console.log('使用LocalStorage');
return new StorageChannelAdapter(this.channelName);
}
}
postMessage(data) {
this.channel.postMessage(data);
}
onMessage(callback) {
this.channel.onMessage(callback);
}
close() {
this.channel.close();
}
}
// BroadcastChannel适配器
class BroadcastChannelAdapter {
constructor(channelName) {
this.channel = new BroadcastChannel(channelName);
}
postMessage(data) {
this.channel.postMessage(data);
}
onMessage(callback) {
this.channel.onmessage = (event) => callback(event.data);
}
close() {
this.channel.close();
}
}
// LocalStorage适配器
class StorageChannelAdapter {
constructor(channelName) {
this.channelName = channelName;
this.listeners = [];
this.init();
}
init() {
window.addEventListener('storage', (event) => {
if (event.key === this.channelName && event.newValue) {
const data = JSON.parse(event.newValue);
this.listeners.forEach(cb => cb(data.data));
}
});
}
postMessage(data) {
const message = {
data: data,
timestamp: Date.now()
};
localStorage.setItem(this.channelName, JSON.stringify(message));
setTimeout(() => {
localStorage.removeItem(this.channelName);
}, 50);
}
onMessage(callback) {
this.listeners.push(callback);
}
close() {
this.listeners = [];
}
}
// 使用统一接口
const channel = new CrossPageChannel('my_channel');
channel.postMessage({ type: 'hello', content: 'Hello World' });
channel.onMessage((data) => {
console.log('收到消息:', data);
});
暂无评论,快来发表第一条评论吧~