【笔记】用 window.postMessage 进行窗口之间的隐式信息传递

简介: 用 window.postMessage 进行窗口之间的隐式信息传递

一、应用场景描述

vue,通过一个弹出的窗口A的选择内容,打开另一个弹出的窗口B,并传参给窗口B

二、文档说明

window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。

从广义上讲,一个窗口可以获得对另一个窗口的引用(比如 targetWindow = window.opener),然后在窗口上调用 targetWindow.postMessage() 方法分发一个 MessageEvent 消息。接收消息的窗口可以根据需要自由处理此事件 (en-US)。传递给 window.postMessage() 的参数(比如 message )将通过消息事件对象暴露给接收消息的窗口。

三、总结

划重点:

  • 跨源通信(也可以理解为我们常说的跨域):不同ip、不同端口、不同协议;
  • 客户端之间通信

postMessage()的两个参数:

  • message:它是要发送到另一个窗口的数据(字符串或对象);
  • targetOrigin:它是发送消息的窗口的URL 。目标窗口的协议,端口和主机名必须与要发送的消息的此参数匹配。设置“*”将匹配任何URL,但不建议用于安全风险。

MessageEvent的四个属性:

  • message 属性表示该message 的类型;
  • data 属性为 window.postMessage 的第一个参数;
  • origin 属性表示调用window.postMessage() 方法时调用页面的当前状态;
  • source 属性记录调用 window.postMessage() 方法的窗口信息。
注:为了安全,一定要做好信息验证!

四、小案例

1.窗口通信

  • 打开百度官网页面(窗口1),在浏览器的console中输入:
window.addEventListener('message',event=>{
  if (event.source === 'https://www.baidu.com' && event.data.key !== '口令:宝塔镇河妖') return;
  console.log(event.data.message);
  event.source.postMessage({key: '口令:天王盖地虎', message: '通过!'}, 'https://www.baidu.com');
});
window.open('https://www.baidu.com')
// 窗口2中可见“通过!”
  • 在新打开的百度页面(窗口2)中输入:
window.addEventListener('message',event => {
  if (event.source === window.opener && event.data.key !== '口令:天王盖地虎') return;
  console.log(event.data.message);
  // 由于窗口1的时间监听中会有消息回复,所以这里如果需要消息回复,必须写到外面,防止死循环
  // 如果有需要,这里可以关闭窗口1
  // window.opener.close()
});
//(即向窗口1发送消息)
window.opener.postMessage({key: '口令:宝塔镇河妖', message: '大王叫我来巡山!'}, 'https://www.baidu.com');
// 窗口1中可见“大王叫我来巡山!”

2.iframe 通信

let myDomain = 'http://xxx.com';
let iframe = document.getElementById('myIFrame').contentWindow;

//周期性的发送消息
setInterval(function(){
    let message = new Date().getTime();
    console.log('发送: ' + message);
    win.postMessage(message, myDomain);
},6000);

//监听消息反馈
window.addEventListener('message',event => {
    if(event.origin !== 'http://yyy.com') return;
    console.log('反馈: ',event.data);
},false);
let myDomain = 'http://yyy.com';
window.addEventListener('message',function(event) {
    if(event.origin !== 'http://xxx.com') return;
    console.log('接收: ' + event.data,event);
    event.source.postMessage('ok!', event.origin); // 反馈消息原路返回
},false);

思考:两个没有因果关系的窗口是否可以使用这种方式通信?


模板选择:

解释:
这里用到了window.postMessage(),我的理解是:窗口A发出广播,需要参数a的,给我发个needA,然后打开窗口B,窗口B在渲染前,对它的发起者(window.opener)发出消息needA,然后就成功收到参数a,接下来关闭窗口A。

相关文章
|
C# 数据安全/隐私保护
C# 窗体之间参数互相传递的两种方法与使用
C# 窗体之间参数互相传递的两种方法与使用
|
存储 安全 Windows
Win32子窗口创建,子窗口回调函数,消息堆栈,逆向定位子窗口消息处理过程
Win32子窗口创建,子窗口回调函数,消息堆栈,逆向定位子窗口消息处理过程
|
JavaScript
element-ui中下拉command传递多参数事件封装
element-ui中下拉command传递多参数事件封装
547 0
element-ui中下拉command传递多参数事件封装
SwiftUI—如何实现对视图显示和消失事件的监听
SwiftUI—如何实现对视图显示和消失事件的监听
709 0
SwiftUI—如何实现对视图显示和消失事件的监听
|
API C#
艾伟_转载:把事件当作对象进行传递
  最近在琢磨一些事情,和API设计有关。API设计在很多时候是和语言特性有关的,因此如Java这样的语言,在API设计时会处处受到压抑。而C#就能够出现如Moq或Fluent NHIbernate这样的项目。
876 0
|
JavaScript 前端开发 数据安全/隐私保护
JavaScript之EventListener事件的传递顺序--冒泡和捕获传播
演示监听事件的传播顺序以及如何阻止这种传播。冒泡和捕获传播
1231 0
|
测试技术 Windows 容器
背水一战 Windows 10 (69) - 控件(控件基类): UIElement - Manipulate 手势处理, 路由事件的注册, 路由事件的冒泡, 命中测试的可见性
原文:背水一战 Windows 10 (69) - 控件(控件基类): UIElement - Manipulate 手势处理, 路由事件的注册, 路由事件的冒泡, 命中测试的可见性 [源码下载] 背水一战 Windows 10 (69) - 控件(控件基类): UIElement - Manip...
1141 0
|
Windows
背水一战 Windows 10 (68) - 控件(控件基类): UIElement - Pointer 相关事件, Tap 相关事件, Key 相关事件, Focus 相关事件
原文:背水一战 Windows 10 (68) - 控件(控件基类): UIElement - Pointer 相关事件, Tap 相关事件, Key 相关事件, Focus 相关事件 [源码下载] 背水一战 Windows 10 (68) - 控件(控件基类): UIElement - Poin...
1216 0
|
程序员
错误:“ResourceDictionary”根元素需要 x:Class 特性来支持 XAML 文件中的事件处理程序。请移除 MouseLeftButtonDown 事件的事件处理程序.
原文:错误:“ResourceDictionary”根元素需要 x:Class 特性来支持 XAML 文件中的事件处理程序。请移除 MouseLeftButtonDown 事件的事件处理程序. 转载于(https://social.
2395 0