7

前言

需求背景:

最近开发管理系统,需要在本页面跳转到一个图片管理系统上传图片,上传成功后返回图片链接,然后返回管理系统,显示图片

实现思路:

  1. 上传图片时,需要在本窗口跳转到图片管理系统,并且两个系统之间要通信
  2. 考虑到两个系统是不同的端口号,存在跨域问题,这时发现HTML5新增了一个API-window.postMessage(),于是就决定用iframe结合window.postMessage()实现
  3. 在页面中嵌入一个iframe,将图片管理系统嵌入到当前的管理系统中,结合window.postMessage()实现跨域通信

项目背景

  • 该管理系统基于React.js搭建,在此简称为A页面,地址为http://www.blogoog.com:8000
  • 图片管理系统基于Vue.js搭建,在此简称为B页面,地址为http://www.blogoog.com:8088

具体实现

参考资料

1、A页面使用到的语法

window.postMessage()

otherWindow.postMessage(message, targetOrigin, [transfer]);
  • otherWindow:其他窗口的一个引用(在这里我使用了iframe的contentWindow属性)
  • message:将要发送到其他window的数据(可以不受限制的将数据对象安全的传送给目标窗口而无需自己序列化,原因是因为采用了结构化克隆算法
  • targetOrigin:接收信息的URL(在这里我当然填的B页面的URL)
  • transfer:可选参数(在这里我没使用)

具体参考:window.postMessage()-MDN

window.addEventListener('message', receiveMessage, false);

target.addEventListener(type, listener, options);
  • type:表示监听事件类型的字符串
  • listener:当所监听的事件类型触发时,会通知的一个对象或者一个函数
  • potions:可选参数(在此我用false,表示在listener被调用之后不会自动移除)

具体参考:addEventListener-MDN

receiveMessage = (event) => {}

  • event.data:从另一个window传递过来的对象(包含传递过来的所有信息)
  • event.origin||event.originalEvent.origin:window.postMessage()发送消息的目标URL
  • event.source:对发送消息的窗口对象的引用

注意点!!!

  • 在页面内嵌入iframe页面的情况下,需要等到页面内的iframe页面,也就是B页面加载完成之后,才能进行postMessage跨域通信
  • event.origin中的origin不能保证是该窗口的当前origin或者未来origin,因为postMessage被调用后,可能会被导航到不同的位置,所以需要做个异常情况判断处理origin !== 'http://www.blogoog.com:8088'

2、B页面使用到的语法

top.postMessage('data', 'http://www.blogoog.com:8000')

  • 参考上面A页面的语法
  • 为什么用top而不用window下面再讲

window.addEventListener('message', receiveMessage, false);

  • 参考上面A页面的语法

receiveMessage = (event) => {}

  • 参考上面A页面的语法

window.postMessage()中的window到底是啥?

始终是你需要通信的目标窗口

  • A页面中:A页面向B页面发送跨域信息,window就是在A页面中嵌入的iframe指向的B页面的window,即:iframe.contentWindow
  • B页面中:B页面想A页面发送跨域信息,window就是A页面的window,在这里因为B页面时嵌入到A页面中的,对于B页面来讲,window就是top或者parent

需要特别注意的坑

  1. 一定要等A页面嵌入的B页面加载完成之后,再进行postMessage跨域通信
  2. 一定要对origin做判断,去掉不是来自我们目标窗口的origin,防止来自其他origin的攻击
  3. 着重注意window.postMessage()中window的用法,明确目标窗口的window

献上代码

A页面


B页面

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/dev...


pitaojin
326 声望36 粉丝