同源页面
广播模式,页面将消息通知给一个中转,中转再通知给各个页面。中转可以是一个 BroadCast Channel 实例、一个 Service Worker 或是 LocalStorage。
BrocastChannel
BrocastChannel可以实现同源下浏览器不同窗口,tab页,frame或frame下的浏览器上下文之间的通信。
// a页面
var bc = new BroadcastChannel('qwer')
bc.postMessage('发送数据')
// b页面
var bc = new BroadcastChannel('qwer')
bc.onmessage = function(e) {
console.log(e)
}
/** 消息发送后,所有连接到该频道的 BrocastChannel对象上都会触发 meaasge事件,
该事件没有默认行为,可以使用`onmessage`事件处理程序来定义一个函数处理消息
**/
LocalStorage
LocalStorage是前端常用的本地存储,当LocalStorage变化是,会触发storage事件,发送消息时,将消息写入LocalStorage中,然后在各个页面中,通过监听storage事件即可收到通知。
// a页面
window.addEventListener('storage', function(e) {
console.log(e)
})
// b页面
localStorage.setItem('qwer', 10000)
Service Worker
Service Worker与页面通信
前端跨页面通信的方法
共享存储 + 长轮询模式
SharedWorker
SharedWorker可以开启后台线程运行脚本,并且多个页面之间可以共享,通过port.postMessage发送消息,通过监听message
事件实现。如果a页面向后台线程发送消息,后台线程触发message
事件后再发送的消息只能被a页面接收,即SharedWorker可以一个线程处理不同的页面逻辑,然后将结果返回对应的页面。
- 根据以上原理,在SharedWorker脚本中设置共享数据以实现页面间的通信
//可以在chrome://inspect中对子线程中的代码进行调试
onconnect = function(e) {
console.log(e)
const port = e.ports[0]
port.onmessage = function(event){
console.log(event)
port.postMessage(event.data)
}
}
页面1中的代码
var sharedWorker = new SharedWorker('./shareWorker.js', 'cpc')
sharedWorker.port.postMessage({
a: 1,
b: 2
})
// 发送数据,此时共享数据的值已经被更改
页面2中的代码
var sharedWorker = new SharedWorker('./shareWorker.js', 'cpc')
sharedWorker.port.postMessage({ get: true })
// 如果需要实时更新的话,可能需要`setInterval`进行轮询
indexDB方案
非同源页面
非同源页面之间的通信通过iframe
实现。各个需要通信的页面加载应该相同的iframe
,这些iframe
之间使用的是同一个url
,属于同源,可以相互通信,接收到消息后postMessage
到主页面即可。
// iframe中的代码
const bc = new BroadcastChannel('cpc')
window.addEventListener('message', function(e) {
console.log(e)
if(e.origin === 'https://magazine.heytapimage.com' || e.origin === 'https://magazine-static-cpc.heytapimage.com') {
bc.postMessage(e.data)
console.log('bc postMessage')
}
})
bc.onmessage = function(e) {
window.parent.postMessage(e.data, 'https://magazine.heytapimage.com') // 支持传入指定域名或*
console.log('bc receiveMessage')
}
a页面的代码
<iframe src="https://dhfs-test-cpc.wanyol.com/iframe.html"></iframe>
<script>
window.frames[0].window.postMessage({
atob: true,
numb: 11,
desc: 'a页面向b页面发送的数据'
}, 'https://dhfs-test-cpc.wanyol.com');
</script>
b页面的代码
<iframe src="https://dhfs-test-cpc.wanyol.com/iframe.html"></iframe>
<script>
window.addEventListener('message', function (e) {
console.log('b页面接收到数据')
if(e.data.atob) {
console.log(e.data)
}
});
</script>