持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情
🎈大家好,我是
橙橙子,新人初来乍到,请多多关照~📝小小的前端一枚,分享一些日常的学习和项目实战总结~
😜如果本文对你有帮助的话,帮忙点点赞呀!ღ( ´・ᴗ・` )比心~
一、同源页面间的跨页面通信
1. BroadCast Channel
BroadCast Channel 可以创建一个用于广播的通信频道。当所有页面都监听同一频道的消息时,其中某一个页面通过它发送的消息就会被其他所有页面收到。
创建一个标识为Test的频道:
const bc = new BroadcastChannel('Test');
页面可以通过onmessage来监听被广播的消息
bc.onmessage = function (e) {
const data = e.data;
const text = '[receive] ' + data.msg + ' —— tab ' + data.from;
console.log('[BroadcastChannel] receive message:', text);
};
发送消息时只要调用实例上的postMessage方法即可
bc.postMessage(mydata);
2. Service Worker
Service Worker 是一个可以长期运行在后台的 Worker,能实现与页面的双向通信。多页面共享间的 Service Worker 可以共享,将 Service Worker 作为消息的处理中心(中央站)即可实现广播效果。
在页面注册 Service Worker
/* 页面逻辑 */
navigator.serviceWorker.register('../util.sw.js').then(function () {
console.log('Service Worker 注册成功');
});
其中../util.sw.js是对应的 Service Worker 脚本。Service Worker 本身并不自动具备“广播通信”的功能,需要我们添加些代码,将其改造成消息中转站:
/* ../util.sw.js Service Worker 逻辑 */
self.addEventListener('message', function (e) {
console.log('service worker receive message', e.data);
e.waitUntil(
self.clients.matchAll().then(function (clients) {
if (!clients || clients.length === 0) {
return;
}
clients.forEach(function (client) {
client.postMessage(e.data);
});
})
);
});
我们在 Service Worker 中监听了message事件,获取页面(C端)发送的信息。通过self.clients.matchAll()方法获取当前注册了Service Worker 的所有页面,通过调用每个页面(C端)的postMessage方法,向页面发送消息。这样就把从某页面收到的消息通知给了其他页面。
在页面监听 Service Worker 发送来的消息
/* 页面逻辑 */
navigator.serviceWorker.addEventListener('message', function (e) {
const data = e.data;
const text = '[receive] ' + data.msg + ' —— tab ' + data.from;
console.log('[Service Worker] receive message:', text);
});
当需要同步消息时,可以调用 Service Worker 的postMessage方法:
/* 页面逻辑 */
navigator.serviceWorker.controller.postMessage(mydata);
3. LocalStorage
LocalStorage 是前端最常用的本地存储。
当 LocalStorage 变化时,会触发storage事件。利用这个特性,我们可以在发送消息时,把消息写入到某个 LocalStorage 中;然后在各个页面内,通过监听storage事件即可收到通知。
window.addEventListener('storage', function (e) {
if (e.key === 'ctc-msg') {
const data = JSON.parse(e.newValue);
const text = '[receive] ' + data.msg + ' —— tab ' + data.from;
console.log('[Storage I] receive message:', text);
}
});
在各个页面添加如上的代码,即可监听到 LocalStorage 的变化。当某个页面需要发送消息时,只要使用我们熟悉的setItem方法即可
mydata.st = +(new Date);
window.localStorage.setItem('ctc-msg', JSON.stringify(mydata));
在mydata上添加了一个取当前毫秒时间戳的.st属性。storage事件只有在值真正改变时才会触发。
window.localStorage.setItem('test', '123');
window.localStorage.setItem('test', '123');
由于第二次的值'123'与第一次的值相同,所以以上代码只会在第一次setItem时触发storage事件。因此我们通过设置st来保证每次调用时一定会触发storage事件。
总结
上面介绍了三种实现跨页面通信的方式,有Broadcast Channel, Service Worker,storage事件,三种都是“广播模式”,一个页面将消息通知给一个“中央站”,再由“中央站”通知给各个页面。