浏览器跨窗口通信
最近做需求遇到的小功能: 从A页面新开个窗口打开B页面,B页面完成一系列操作后,需要自动关闭B页面,然后A页面完成一个刷新的动作。
理下逻辑:
1、A 页面打开 B页面,A页面可以拿到B页面的window
js
const newWindow= window.open(B)
2、B页面可以通过window.opener.postMessage向A页面发消息
js
window.opener.postMessage('submitSuccess', window.location.origin);
3、A页面通过window.addEventListener监听B页面的消息然后刷新
js
window.addEventListener('message', (event) => {
if (event.data === 'submitSuccess') {
console.log('监听到B消息执行下一步')
Freshpage();
}
})
如果B页面中通过微前端嵌入C页面,C页面通过window.parent.postMessage()向B页面发送消息
js
window.parent.postMessage('submitSuccess', window.location.origin)
window.parent.postMessage('submitSuccess', window.location.origin)
通常在以下场景中使用: 一、跨域通信场景
- Iframe 与父窗口通信:
- 当网页中包含一个 iframe,并且 iframe 中的内容与父窗口来自不同的源(域名、协议、端口不同)时,可以使用这种方式向父窗口传递消息。
- 例如,在一个在线文档编辑系统中,文档编辑页面可能以 iframe 的形式嵌入在主页面中。当用户在文档编辑页面完成提交操作后,可以使用这个方法向主页面发送一个“提交成功”的消息,以便主页面进行相应的状态更新或其他操作。
- 跨窗口通信:
- 有时候可能会有多个窗口同时打开,并且这些窗口之间需要进行通信。在这种情况下,可以使用
postMessage
方法在不同窗口之间传递消息。 - 比如,一个在线协作工具可能同时打开了多个窗口用于不同的任务,当一个窗口中的操作完成后,可以向其他相关窗口发送消息以同步状态。 二、Web 组件通信场景
- 自定义 Web 组件内部与外部通信:
- 开发自定义 Web 组件时,组件内部的逻辑可能需要向包含该组件的页面传递消息。
- 例如,一个自定义的表单组件,当表单提交成功后,可以通过这种方式向使用该组件的页面发送一个提交成功的消息,以便页面进行后续处理,如显示成功提示、更新页面状态等。
- 多个独立开发的 Web 组件之间通信:
- 在复杂的 Web 应用中,可能会使用多个独立开发的 Web 组件,这些组件之间有时需要进行通信。
- 比如,一个电商网站的购物车组件和结算组件可能需要进行交互,当购物车中的商品提交成功后,购物车组件可以使用
postMessage
向结算组件发送消息,以便结算组件更新订单总价等信息。
window.opener.postMessage()
主要适用于以下场景: 一、跨页面通信场景
- 由父页面打开子页面并通信:
- 当一个网页(父页面)通过
window.open()
方法打开另一个网页(子页面)时,可以使用window.opener.postMessage()
实现从子页面向父页面传递信息。 - 例如,在一个在线购物网站中,父页面可能打开一个支付页面作为子页面。当支付成功后,子页面可以使用这个方法向父页面发送支付成功的消息,以便父页面更新订单状态或显示成功提示。
- 多窗口协作场景:
- 在一些复杂的应用中,可能需要同时打开多个窗口进行协作。通过
window.opener.postMessage()
可以在不同窗口之间传递消息,实现数据同步或协调操作。 - 比如,一个设计软件可能同时打开多个编辑窗口,当一个窗口中的操作影响到其他窗口时,可以使用这个方法进行通知。 二、安全的跨源通信场景
- 不同源页面间通信:
- 由于
postMessage
可以进行安全的跨源通信,所以在父页面和子页面来自不同源(不同域名、协议或端口)的情况下,window.opener.postMessage()
仍然可以有效地传递消息。 - 例如,一个企业内部的不同系统可能需要在浏览器中进行交互,即使它们运行在不同的域名下,也可以通过这种方式进行安全的通信。
- 防止跨站脚本攻击(XSS):
postMessage
提供了一种安全的通信机制,可以避免一些常见的安全漏洞,如 XSS 攻击。通过验证消息的来源,可以确保只接收来自可信窗口的消息。- 比如,在接收
postMessage
发送的消息时,可以检查event.origin
,确保消息来自预期的源,从而防止恶意页面发送虚假消息进行攻击。
window.opener.postMessage()
和window.parent.postMessage()
主要有以下区别:
一、作用对象不同
window.opener
:
- 通常用于在通过
window.open()
打开新窗口后,新窗口向打开它的窗口(即父窗口)发送消息。 - 例如,页面 A 使用
window.open()
打开了页面 B,在页面 B 中可以使用window.opener.postMessage()
向页面 A 发送消息。 - 如果页面 A 被关闭或者没有通过
window.open()
打开的页面使用window.opener
会返回null
window.parent
:
- 主要用于在一个框架集(frameset)或者一个页面中包含
iframe
的情况下,子框架向父框架发送消息。 - 比如,在一个包含多个
iframe
的页面中,某个iframe
内的代码可以使用window.parent.postMessage()
向包含它的页面发送消息。
二、适用场景不同
window.opener.postMessage()
:
- 只适用于明确知道两个页面之间是通过
window.open()
打开关系的场景。 - 常用于在新打开的窗口完成某些操作后,通知打开它的窗口进行相应的处理。
window.parent.postMessage()
:
- 更适用于页面结构中存在嵌套关系,如框架集或
iframe
的场景。 - 例如在一个复杂的 Web 应用中,不同部分的功能可能分别放在不同的
iframe
中,通过这种方式进行通信可以实现各部分之间的协调工作。