一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
在前端web网页开发过程中,经常会遇到新开同域或跨域的第三方页面。新的页面就会涉及必要参数传递、页面间通信的问题。标签页传参和标签页通信是不同的意思,常见的标签页之间的传参方式有URL、Storage(包括localStorage和sessionStorage),Vue项目还可以使用vue-router、Vuex等;如果要实现标签页之间的通信又有哪些方法呢?本文主要介绍三种方式:websocket、localStorage、sharedWorker。
使用WebSocket
websocket是一种可实现客户端和服务端双向通信的协议,不同于HTTP协议。HTTP协议只能由客户端发起通信,服务端不能主动发起。有了websocket,怎么实现标签页之间的通信呢。很简单,tabA实现一个WebSocket,并拥有发送和接收消息的能力,tabB也实现一个WebSocket,也拥有发送和接收消息的能力。两者将消息经由服务器发送给对方,在收到消息后处理。
这种方式可以避免跨域问题,但是缺点是需要服务端做中间处理,如果只是简单的两个标签页之间的通信,使用WebSocket有点"大材小用"。
使用localStorage(推荐)
根据Storage的特性,localStorage只能访问同域的数据。因此这些标签页需要同域才能使用localStorage来通信。首先在tabA监听storage是否变化,然后跳转到tabB后,在tabB页面修改localStorage里面的数据,tabA就能根据监听到的storage变化,过滤出是否有自己想要的值,注意此处不能使用sessionStorage。sessionStorage无法在多个标签页之间共享,哪怕是同源、同页面。
实现代码
// tabA
window.addEventListener('storage', event => {
console.log('监听storage改变', event, event.key, event.newValue);
});
// tabB
const btn = document.createElement('button');
ducoment.body.appendChild(btn);
btn.addEventListener('click', () => {
localStorage.setItem('tabBInfo', JSON.stringify({
text: 'this is tabB',
time: Date.now(), // 使用当前时间,保证每次发消息都是不同的
}))
})
注意事项
- 多个标签页必须同源
- 此方案主要是监听Storage的变化实现通信,因此只有改变了localStorage的值才能监听到
使用sharedWorker
js是单线程执行,可通过webWorker开启"多线程"。webWorker不能操作dom,但是可以执行某些任务,sharedWorker作为webWorker中的一种,可用于同域页面间的通信。
实现代码
// worker.js
const ports = new Set()
onconnect = event => {
let port = event.ports[0]
ports.add(port)
port.onmessage = e => {
ports.forEach(p => {
p.postMessage(e.data)
})
}
port.start()
}
// tabA
const worker = new SharedWorker('./worker.js')
worker.port.onmessage = e => {
console.log('tabA 收到消息:', e.data)
}
// tabB
const worker = new SharedWorker('./worker.js')
const btn = document.createElement('button');
ducoment.body.appendChild(btn);
btn.addEventListener('click', () => {
worker.port.postMessage('来自tabB的消息')
})
注意事项
- SharedWorker可以被多个窗口页面使用,但是这些页面必须是同源的,即同协议、端口、host。
- SharedWorker通信依赖于端口,因此需要在node环境下执行,而不是直接访问html
- 发消息采用postMessage,接收消息采用onmessage
- SharedWorker不支持ie11,兼容性尚可
总结
本文一共列举了三种多标签页间的通信方式,根据场景不同可选择不同的实现方式,优缺点如下:
- WebSocket 可跨域通信,但是存在服务端成本
- localStorage不可跨域共享,简单易上手,同域通信更推荐。关键是监听Storage的变化
- SharedWorker不可跨域通信,存在兼容性,且需要在node环境下才能执行。对比localStorage,SharedWorker监听的是端口间的通信,发送和接收消息更灵活;localStorage则需要保证修改和监听key值保持一致,如果需要的key值很多,不管是修改方还是接收方,代码都会比较冗余。
原创不易,转载请注明出处。