Alan's blog Alan's blog
首页
思考感悟
技术学习
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Alan wu

前端小时
首页
思考感悟
技术学习
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 计算机基础

  • 架构设计

  • HTTP网络

  • Node

  • 小程序

  • 设计

  • JavaScript

  • HTML&CSS

  • 浏览器

    • 一次看懂如何解决跨域
    • 浏览器按下回车发生了什么
    • 系统总结浏览器缓存
    • 微信扫码登录原理分析
    • 如何实现单点登录(single sign on)
    • 如何实现浏览器不同Tab页面通信
      • 如何实现浏览器不同Tab页面通信
      • 01 前言
      • 02 通信方法
      • 03 小结
    • cookie、sessionStorage、localStorage区别
  • webpack

  • 运维

  • Vue&React

  • 技术
  • 浏览器
alanwu
2020-03-06
目录

如何实现浏览器不同Tab页面通信

# 如何实现浏览器不同Tab页面通信

闻道有先后,术业有专攻

# 01 前言

我们知道,浏览器打开一个Tab页面就会打开一个进程,同时会开启若干个线程,这就涉及到进程之间通信的问题。一般来说单纯使用HTML5的相关特性是无法完成的,我们需要其他的方法来实现。

# 02 通信方法

我们可以分几种情况来讨论这个问题。

1、postMessage

页面A通过window.open方法打开另一个页面B,或者B页面通过iframe的形式嵌入A页面,这种情况比较简单,可以使用HTML5的API来完成通信。我们知道window是一个全局对象,前提是页面A或者页面B可以获取另一个页面的window对象,完成单向通信。

//B页面
window.addEventListner('message',(e)=>{
    let {data,source,origin} = e;
    source.postMessage('message echo','/');
});
1
2
3
4
5

postMessage的第一个参数为消息实体,它是一个结构化对象,即可以通过“JSON.stringify和JSON.parse”函数还原的对象;第二个参数为消息发送范围选择器,设置为“/”意味着只发送消息给同源的页面,设置为“*”则发送全部页面。

2、localStorage

此方法适用于同源范围的通信,因此可以通过共享localStorage的方式进行通信,通过约定localStorage的某一个名,然后共享方式通信。通过window对象侦听storage事件,会侦听localStorage对象的变化事件(包括item的添加、修改和删除)

//A 页面
window.addEventListener("storage", function(ev){
    if (ev.key == 'message') {
        // removeItem同样触发storage事件,此时ev.newValue为空
        if(!ev.newValue)
            return;
        var message = JSON.parse(ev.newValue);
        console.log(message);
    }
});
function sendMessage(message){
    localStorage.setItem('message',JSON.stringify(message));
    localStorage.removeItem('message');
}
// 发送消息给B页面
sendMessage('this is message from A');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//B 页面
window.addEventListener("storage", function(ev){
    if (ev.key == 'message') {
        // removeItem同样触发storage事件,此时ev.newValue为空
        if(!ev.newValue)
            return;
        var message = JSON.parse(ev.newValue);
        // 发送消息给A页面
        sendMessage('message echo from B');
    }
});
function sendMessage(message){
    localStorage.setItem('message',JSON.stringify(message));
    localStorage.removeItem('message');
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

3、BroadcastChannel

这种方法与localStorage的思想一样。

// A.html
const channel = new BroadcastChannel('tabs')
channel.onmessage = evt => {
  // evt.data
}

// B.html
const channel = new BroadcastChannel('tabs')
channel.postMessage('hello')
1
2
3
4
5
6
7
8
9

4、WebSocket

WebSocket可以实现全双工通信,自然可以实现多个标签页之间的通信的问题。

WebSocket连接必须由浏览器发起,特点:

(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

5、cookie+setInterval

在页面A设置一个使用 setInterval 定时器不断刷新,检查 Cookies 的值是否发生变化,如果变化就进行刷新的操作。

由于 Cookies 是在同域可读的,所以在页面 B 审核的时候改变 Cookies 的值,页面 A 自然是可以拿到的。这样做确实可以实现我想要的功能,但是这样的方法相当浪费资源。虽然在这个性能过盛的时代,浪费不浪费也感觉不出来,但是这种实现方案,确实不够优雅。

6、sharedWorker

SharedWorker本身并不是为了解决通讯需求的,它的设计初衷应该是类似总控,将一些通用逻辑放在SharedWorker中处理,不过因为也能实现通讯。

// A.html
var sharedworker = new SharedWorker('worker.js')
sharedworker.port.start()
sharedworker.port.onmessage = evt => {
  // evt.data
}

// B.html
var sharedworker = new SharedWorker('worker.js')
sharedworker.port.start()
sharedworker.port.postMessage('hello')

// worker.js
const ports = []
onconnect = e => {
  const port = e.ports[0]
  ports.push(port)
  port.onmessage = evt => {
    ports.filter(v => v!== port) // 此处为了贴近其他方案的实现,剔除自己
    .forEach(p => p.postMessage(evt.data))
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 03 小结

其实页面之间的通信用的不是很多,但是在技术发展的同时我们都要关注一下,特别是为什么能够进行通信,每一个Tab背后都是由什么组成的,这些了解清楚最好。还有关于进程和线程的区别,知道这些才会更好的理解。

参考文章:

  • Communication between tabs or windows
  • 跨浏览器tab页面的通信解决方案尝试
  • 浏览器多个标签页之间的通信
  • 跨页面通信的各种姿势

编辑 (opens new window)
上次更新: 2023/05/13, 23:08:05
如何实现单点登录(single sign on)
cookie、sessionStorage、localStorage区别

← 如何实现单点登录(single sign on) cookie、sessionStorage、localStorage区别→

最近更新
01
HTTPS:让数据传输更安全
06-15
02
沙盒:页面和系统之间的隔离墙
06-15
03
CSRF攻击:陌生链接不要随便点
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2023 Alan Wu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式