ITPub博客

首页 > 应用开发 > Html/css > 浏览器多窗口通信有效实践总结

浏览器多窗口通信有效实践总结

原创 Html/css 作者:mxrpz196 时间:2026-01-29 15:14:52 0 删除 编辑

如何跨越不同窗口通信

在现代 Web 开发中,多个窗口或标签页之间的通信成为了越来越常见的需求,尤其是在应用需要同步数据、共享状态或进行实时更新的场景中。不同窗口间的通信方式有很多种,选择合适的方式可以大大提高开发效率和用户体验。本文将详细介绍几种常见的浏览器多窗口通信技术,并结合实际代码示例,分析它们的优缺点及兼容性。

1、window.postMessage的使用实践

window.postMessage 是一种用于跨域或同域窗口间安全通信的 API。通过 postMessage,我们可以轻松实现父子窗口、同域不同标签页或跨域之间的数据传递。

以下为实际运用中常用的2种用法:

1.1 iframe使用获得窗口引用

通过  window.postMessage,父页面可以与嵌套的  iframe 进行通信。关键是要正确获得  iframe 的引用,然后通过该引用发送消息

父页面 parent.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<button > "send()" >向iframe窗口发送消息< /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 > "send()" >向父窗口发送消息< /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/ 进行通信

1.2 window.open使用,获取窗口引用

通过  window.open 打开一个新的窗口或标签页时,我们可以获得新窗口的引用,并通过  postMessage 实现通信。

父页面 parent.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<button > "openWin()" >打开新窗口< /button >
<button > "send()" >发送消息< /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 > "send()" >向父窗口发送消息< /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 在大多数现代浏览器中得到支持。需要注意:如果打开的窗口被浏览器阻止弹出,通信无法进行。

2、客户端存储 + 定时器实时刷新监听【不推荐】

通过客户端存储(如  cookie、 localStorage 或  sessionStorage)结合定时器(如  setInterval 或  requestAnimationFrame),可以实现同源域名下不同窗口之间的通信。此方式利用定时器定时检查存储值的变化,但缺点是浪费性能资源,且数据更新不够实时

父页面 parent.html

1
2
//  父页面向 storage 写入数据
localStorage.setItem( 'message' ,  'Hello from Page' );

 

子页面child.html
1
2
3
4
5
6
7
//  子页面 定时检查 localStorage 变化
setInterval(() => {
   const message = localStorage.getItem( 'message' );
   if  (message) {
     console.log( 'travel.firstfeed.com.cn :' , message);
   }
}, 1000);

  

3、StorageEvent 事件监听

当一个页面修改了  localStorage 或  sessionStorage,其他同源的页面可以通过监听  storage 事件来获取更新。此方法适合同一域下多个页面之间的通信。

父页面 parent.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<button > "send()" >向子窗口发送消息< /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 > "send()" >向父窗口发送消息< /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。它仅在同源的多个页面之间有效,无法跨域使用。

4、Broadcast Channel

BroadcastChannel API 允许同源的多个窗口、标签页、iframe 或 Web Worker 之间进行消息广播。这种方法非常适合同一应用中多个窗口或标签页之间的实时通信。

父页面 parent.html

1
2
3
4
5
6
7
8
9
10
11
12
<button > "send()" >向子窗口发送消息< /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 > "send()" >向父窗口发送消息< /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 或较旧的浏览器版本。

5、SharedWorker

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.js
const ports = [];
self.> function  (event) {
   const port = event.ports[0];
   ports.push(port);  //  存储 port(端口)
   //  初始化发送消息
   port.postMessage( 'Hello from SharedWorker!' );
   //  监听消息
   port.> function  (e) {
     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,这样就可以看到当前页面中的 SharedWorker

edge游览器: edge://inspect/#workers

 父页面 parent.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<button > "send()" >向子窗口发送消息< /button >
<script>
   //  创建 SharedWorker 实例
   const worker = new SharedWorker( "worker.js" );
   //  接收来自 worker 的消息
   worker.port.> function  (event) {
     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 > "send()" >向父窗口发送消息< /button >
<script>
   //  创建 SharedWorker 实例
   const worker = new SharedWorker( "worker.js" );
 
   //  接收来自 worker 的消息
   worker.port.> function  (event) {
     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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-01-12

  • 博文量
    22
  • 访问量
    26015