浏览器跨页签通信的几种常见的方法
监听localStorage
实现步骤: 页面A:
window.localStorage.setItem('open_about', Date.now()+'')
注意存储的值不能相同不然不会触发监听事件
页面B:
window.addEventListener('storage', function(e) {
console.log('11111111',e)
})
使用Broadcast Channel API
1.定义一个channel.js
const channel = new BroadcastChannel('demo_1')
export function sendMsg(type, content) {
channel.postMessage({
type,
content
})
}
export function listenMsg(callback) {
const handler = (e) => {
callback && callback(e.data)
}
channel.addEventListener('message', handler)
return ()=> {
channel.removeEventListener('message', handler)
}
}
A页面
const clickOpen = () => {
sendMsg('key', '123')
}
B页面
listenMsg((e: Event)=> {
console.log(e)
})
SharedWorker
1.新增sharedWorker.js
let connections = []
onconnect = function (e) {
const port = e.ports[0]
connections.push(port)
port.onmessage = function (event) {
// 广播接收到的消息给所有连接的端口
connections.forEach(conn => {
if (conn !== port) {
conn.postMessage(event.data)
}
})
}
port.start()
}
A页面
const worker = new SharedWorker("sharedWorker.js");
const clickOpen = () => {
worker.port.postMessage(`moment 1111`);
}
B页面
const worker = new SharedWorker("sharedWorker.js");
worker.port.start();
worker.port.onmessage = function (e) {
if (e.data) {
console.log(e.data);
window.close()
}
};
Service Worker
1.新增一个work.js
self.addEventListener("message", function (e) {
e.waitUntil(
self.clients.matchAll().then(function (clients) {
if (!clients || clients.length === 0) {
return;
}
clients.forEach(function (client) {
client.postMessage(e.data);
});
})
);
});
A页面
navigator.serviceWorker.register("worker.js").then(() => {
console.log("注册成功");
});
const clickOpen = () => {
navigator.serviceWorker.controller?.postMessage({
value: `moment ${new Date()}`,
});
}
B页面
navigator.serviceWorker.register("/worker.js").then(() => {
console.log("注册成功");
});
navigator.serviceWorker.onmessage = function (e) {
console.log(e.data.value);
};
Window.postMessage api
A页面
let targetWindow = window.open('http://localhost:5173/about', '_blank');
B页面
window.addEventListener('message', function(event: any) {
// 确保消息来自预期的源
if (event.origin !== 'http://localhost:5173') {
return;
}
const message = event.data;
console.log('Received message:', event);
});
IndexedDB
A页面
// 打开或创建 IndexedDB 数据库
const request = indexedDB.open('messageDatabase', 1);
request.onupgradeneeded = function(event) {
const db = event.target.result; // 创建一个对象存储空间用于存储消息
db.createObjectStore('messages', {
keyPath: 'id',
autoIncrement: true });
};
request.onsuccess = function(event) {
const db = event.target.result; // 向数据库中添加一条新消息
const transaction = db.transaction(['messages'], 'readwrite');
const objectStore = transaction.objectStore('messages');
const message = { content: 'Hello from sender!'
};
objectStore.add(message);
transaction.oncomplete = function() {
console.log('Message sent successfully!'); // 关闭数据库连接
db.close();
};
};
request.onerror = function(event) {
console.error('Error opening database:', event.target.error);
};
B页面
// 打开或创建 IndexedDB 数据库
const request = indexedDB.open('messageDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result; // 创建一个定时器,每隔一段时间轮询数据库中的消息
setInterval(function() { // 创建一个事务
const transaction = db.transaction(['messages'], 'readwrite');
const objectStore = transaction.objectStore('messages'); // 获取存储在对象存储中的所有消息
const request = objectStore.getAll();
request.onsuccess = function(event) {
const messages = event.target.result; // 处理消息
messages.forEach(function(message) {
console.log('Received message:', message.content); // 在处理完消息后,删除该消息
objectStore.delete(message.id);
});
// 关闭事务
transaction.oncomplete = function() {
console.log('Messages processed successfully!');
};
};
request.onerror = function(event) {
console.error('Error retrieving messages:', event.target.error); // 关闭事务
transaction.abort();
};
}, 1000);
};
request.onerror = function(event) {
console.error('Error opening database:', event.target.error);
};
websocket
使用服务器端存储:将需要共享的数据存储在服务器端,标签页之间通过与服务器进行通信来获取和更新数据。可以使用 AJAX、WebSocket 或其他网络通信技术来实现与服务器的数据交互。