如何实现浏览器内多个标签页之间的通信?
引言
实现多个标签页之间的通信,本质上都是通过中介者模式来实现的。因为标签页之间没有办法直接通信,因此我们可以找一个中介者,让标签页和中介者进行通信,然后让这个中介者来进行消息的转发。面试中经常问到的不使用websocket的情况下如何实现一个聊天室,也就是同域名不同标签之间如何通信。通信方法如下:
-
使用 websocket 协议,因为 websocket 协议可以实现服务器推送,是全双工的可以建立一次链接之后持续向服务器推送信息,所以服务器就可以用来当做这个中介者。标签页通过向服务器发送数据,然后由服务器向其他标签页推送转发。
-
使用 localStorage 的方式,我们可以在一个标签页对 localStorage 的变化事件进行监听,使用
storage
事件来实现,然后当另一个标签页修改localStorage数据的时候,其他标签页可以通过监听storage
事件来获取通知并更新相应的数据。这个时候 localStorage 对象就是充当的中介者的角色。
举例
// 在一个标签页中设置localStorage的数据
localStorage.setItem('myData', 'hello from tab 1');
// 在另一个标签页中监听storage事件
window.addEventListener('storage', (event) => {
if (event.key === 'myData') {
console.log('Data has been updated in another tab:', event.newValue);
}
});
// 当在任何一个标签页中修改localStorage的数据时,其他标签页会收到storage事件的通知
注意
:在同一个页面中对localStorage进行修改,是不会触发storage事件的,storage
事件是在其他标签页或同一域名下的其他窗口对localStorage
进行更改时才会被触发。因此,如果你在同一个标签页中进行localStorage
的更改,storage
事件不会被触发。
-
使用 ShareWorker 的方式,shareWorker 会在页面存在的生命周期内创建一个唯一的线程,并且开启多个页面也只会使用同一个线程。这个时候共享线程就可以充当中介者的角色。标签页间通过共享一个线程,然后通过这个共享的线程来实现数据的交换。
-
使用 postMessage 方法,如果我们能够获得对应标签页的引用,就可以使用postMessage 方法,进行通信。