【笔记】用 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);

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序边界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值