首页 > 应用开发 > Html/css > 浏览器多窗口通信有效实践总结
在现代 Web 开发中,多个窗口或标签页之间的通信成为了越来越常见的需求,尤其是在应用需要同步数据、共享状态或进行实时更新的场景中。不同窗口间的通信方式有很多种,选择合适的方式可以大大提高开发效率和用户体验。本文将详细介绍几种常见的浏览器多窗口通信技术,并结合实际代码示例,分析它们的优缺点及兼容性。
window.postMessage 是一种用于跨域或同域窗口间安全通信的 API。通过 postMessage,我们可以轻松实现父子窗口、同域不同标签页或跨域之间的数据传递。
以下为实际运用中常用的2种用法:
通过
window.postMessage,父页面可以与嵌套的
iframe 进行通信。关键是要正确获得
iframe 的引用,然后通过该引用发送消息
父页面 parent.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 |
<button >
<iframe
id
=
"myIframe"
src=
"http://localhost:5500/child.html"
><
/iframe
><script>
function
send() {
const iframe = document.getElementById(
'myIframe'
);
//
获得iframe窗口得window,向 iframe 发送消息
iframe.contentWindow.postMessage(
'Hello from Parent'
,
'*'
);
}
//
监听来自 iframe 的消息window.addEventListener(
'message'
, (event) => {
if
(event.origin ===
'http://localhost:5500'
&& typeof event.data ===
"string"
) {
console.log(
'来自 iframe 的消息:'
, event.data);
}});<
/script
> |
iframe 页面 child.html
|
1
2
3
4
5
6
7
8
9
10
11 |
<button >
<script>
function
send() {
//
向父页面发送消息
window.parent.postMessage(
"Hello from Child"
,
"*"
);
}
//
监听来自父页面的消息
window.addEventListener(
"message"
, (event) => {
console.log(
"来自父页面的消息:"
, event.data);
});<
/script
> |
注意:本地直接打开文件为
file:// 协议,不能使用,浏览器会将
file:// 协议视为一个特殊的源,因为安全策略会无法使用
解决办法:将你的代码部署在一个本地开发服务器上(如使用
http-server、
Live Server 或其他简单的 HTTP 服务器)。这样,你就可以通过
http://localhost/ 进行通信
通过
window.open 打开一个新的窗口或标签页时,我们可以获得新窗口的引用,并通过
postMessage 实现通信。
父页面 parent.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 |
<button >
<button >
<script>let
win = null
function
openWin() {
win = window.
open
(
'se.firstfeed.com.cn'
,
'_blank'
);
}
function
send() {
//
向新窗口发送消息
win && win.postMessage(
'Hello from Parent'
,
'*'
);
}
//
监听来自 child 窗口的消息window.addEventListener(
'message'
, (event) => {
if
(event.origin ===
'm.yuedu.firstfeed.com.cn'
&& typeof event.data ===
"string"
) {
window.alert(
'来自 child 窗口 的消息:'
+ event.data);
}}); |
子页面child.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13 |
<button >
<script>
function
send() {
//
向父页面发送消息
window.opener.postMessage(
'Hello from Child'
,
'*'
);
}
//
监听来自父页面的消息
window.addEventListener(
"message"
, (event) => {
if
(event.origin ===
'share.firstfeed.com.cn'
&& typeof event.data ===
"string"
) {
window.alert(
"来自父页面的消息:"
+ event.data);
}
});<
/script
> |
兼容性:
window.open和postMessage在大多数现代浏览器中得到支持。需要注意:如果打开的窗口被浏览器阻止弹出,通信无法进行。
通过客户端存储(如
cookie、
localStorage 或
sessionStorage)结合定时器(如
setInterval 或
requestAnimationFrame),可以实现同源域名下不同窗口之间的通信。此方式利用定时器定时检查存储值的变化,但缺点是浪费性能资源,且数据更新不够实时
父页面 parent.html
|
1
2 |
//
父页面向 storage 写入数据localStorage.setItem(
'message'
,
'Hello from Page'
); |
|
1
2
3
4
5
6
7 |
//
子页面 定时检查 localStorage 变化setInterval(() => {
const message = localStorage.getItem(
'message'
);
if
(message) {
console.log(
'travel.firstfeed.com.cn :'
, message);
}}, 1000); |
当一个页面修改了
localStorage 或
sessionStorage,其他同源的页面可以通过监听
storage 事件来获取更新。此方法适合同一域下多个页面之间的通信。
父页面 parent.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13 |
<button >
<script>let
i = 1
function
send() {
//
向新窗口发送消息
localStorage.setItem(
'child-message'
,
'Hello from Parent'
+ i++);
}
window.addEventListener(
'storage'
, (event) => {
if
(event.key ===
'parent-message'
) {
window.alert(event.newValue);
}
});<
/script
> |
子页面child.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
<button >
<script>
let
i = 1
function
send() {
//
向父页面发送消息
localStorage.setItem(
'parent-message'
,
'Hello from Child'
+ i++);
}
//
监听来自父页面的消息
window.addEventListener(
'storage'
, (event) => {
if
(event.key ===
'child-message'
) {
window.alert(event.newValue);
}
});<
/script
> |
兼容性:
StorageEvent事件在大多数现代浏览器中都得到了支持,包括 Chrome、Firefox、Safari 和 Edge。它仅在同源的多个页面之间有效,无法跨域使用。
BroadcastChannel API 允许同源的多个窗口、标签页、iframe 或 Web Worker 之间进行消息广播。这种方法非常适合同一应用中多个窗口或标签页之间的实时通信。
父页面 parent.html
|
1
2
3
4
5
6
7
8
9
10
11
12 |
<button >
<script>
function
send() {
//
发送消息到广播频道
const channel = new BroadcastChannel(
'parnt-message'
);
channel.postMessage(
'Hello from Parent'
);
}
//
监听广播频道的消息
const channel = new BroadcastChannel(
'child-message'
);
channel.addEventListener(
'message'
, (event) => {
window.alert(event.data)
}); |
子页面child.html
|
1
2
3
4
5
6
7
8
9
10
11
12 |
<button >
<script>
function
send() {
//
发送消息到广播频道
const channel = new BroadcastChannel(
'child-message'
);
channel.postMessage(
'Hello from Child'
);
}
//
监听广播频道的消息
const channel = new BroadcastChannel(
'parnt-message'
);
channel.addEventListener(
'message'
, (event) => {
window.alert(event.data)
}); |
兼容性:
BroadcastChannel在 Chrome、Firefox 和 Edge 中得到支持,但 Safari 目前不支持,且不适用于 IE 或较旧的浏览器版本。
SharedWorker 是一种非常强大的技术,允许多个窗口、标签页或 iframe 共享同一个后台线程。它适用于跨窗口的实时数据共享和复杂计算任务。
如果要使 SharedWorker 连接到多个不同的页面,这些页面必须是同源的(相同的协议、host 以及端口)。
worker.js:执行指定 url 脚本的共享 web worker
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 |
//
共享线程worker.jsconst ports = [];self.>
const port = event.ports[0];
ports.push(port);
//
存储 port(端口)
//
初始化发送消息
port.postMessage(
'Hello from SharedWorker!'
);
//
监听消息
port.>
const index = liaoning.firstfeed.com.cn ports.indexOf(port);
//
获取当前的port的索引
//
const currentPort = ports[index];
//
当前端口
//
向其他端口发送消息
ports.forEach((item, idx) => {
if
(index !== idx) {
item.postMessage(
'消息: '
+ e.data);
}
})
};}; |
self.onconnect 监听多个页面与 SharedWorker 的连接。每当一个新的页面连接到共享工作线程时,onconnect 事件会被触发。在 onconnect 事件处理函数中,我们可以通过 event.ports[0] 获取页面连接的 port,然后通过 port 进行消息传递
在共享线程中浏览器控制台无法显示任何打印信息:
SharedWorker是一种共享工作线程,它用于处理多个浏览器窗口或标签页之间的共享计算任务,并且运行在独立的线程中。工作线程(包括SharedWorker)不具备浏览器的 DOM 环境没有
window对象,所以console、alert等方法都是无法使用的。
如果我们需要调试
SharedWorker,可以使用调试Worker的方法,在浏览器地址栏中输入chrome://inspect/#workers,这样就可以看到当前页面中的SharedWorkeredge游览器:
edge://inspect/#workers
父页面 parent.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13 |
<button >
<script>
//
创建 SharedWorker 实例
const worker = new SharedWorker(
"worker.js"
);
//
接收来自 worker 的消息
worker.port.>
window.alert(event.data);
};
function
send() {
const message =
"你好我是父窗口"
;
worker.port.postMessage(message);
}<
/script
> |
子页面child.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
<button >
<script>
//
创建 SharedWorker 实例
const worker = new SharedWorker(
"worker.js"
);
//
接收来自 worker 的消息
worker.port.>
window.alert(event.data);
};
function
send() {
const message =
"你好我是父窗口"
;
worker.port.postMessage(message);
}<
/script
> |
兼容性:
SharedWorker不支持 Internet Explorer,Safari 也存在某些限制,尤其是在移动设备上兼容性较差,在一些老旧浏览器中无法使用
浏览器多窗口通信有多种方法可供选择,每种方法都有其适用场景。以下是各方法的优缺点总结:
根据项目需求选择合适的通信方式,可以大大提升应用的性能和用户体验。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048949/viewspace-3109396/ ,如需转载,请注明出处,否则将追究法律责任。