详解使用postMessage解决iframe跨域通信问题


Posted in HTML / CSS onNovember 01, 2019

这周碰到一个让人头疼的需求:要在我的web项目中嵌入另一个第三方web项目。第一时间想到的就是用iframe了,但问题来了,我和第三方web项目是有交互的,这就违反同源策略了,处理跨域问题是最让人头疼的事之一。

需求是这样的,在我的页面点击一些按钮,要实时反馈到iframe子页面,子页面再进行响应。

当时脑子里第一时间想到的解决方案是:用NGINX把两个项目代理到同一域名下。但这样似乎有点小题大做了,有没有更方便快捷的方法呢?

在window对象下有个postMessage方法,是专门用来解决跨域通信问题的。

关于postMessage的详细介绍请戳这里,不过MDN的文档太详细了,导致有些同学看完还是一脸懵逼,下面我们就来看看怎么用postMessage实现iframe跨域通信,当你会用了之后再回去看文档,感觉是完全不同的。

首先我们模拟场景,假设有两个不同源的页面,iframePage.html是index.html的子页面:

<!-- index.html -->

<body style="border:5px solid #333;">

  <h1>this is index</h1>

  <iframe src="./iframePage.html" id='myframe'></iframe>

</body>
<!-- iframePage -->

<body style="border:5px solid #333;">

  <h1>this is iframePage</h1>

</body>

现在这两个iframe是无法通信,因为它们是不同源的(假设存在跨域问题),这时候就要用到postMessage了。

我们先试着从父页面向子页面发送一条消息:

// idnex.html

//获取iframe元素
iFrame = document.getElementById('myframe')

//iframe加载完毕后再发送消息,否则子页面接收不到message
iFrame.onload = function(){

  //iframe加载完立即发送一条消息
  iFrame.contentWindow.postMessage('MessageFromIndex1','*');

}

我们知道postMessage是挂载在window对象上的,所以等iframe加载完毕后,用iFrame.contentWindow获取到iframe的window对象,然后调用postMessage方法,相当于给子页面发送了一条消息。

postMessage方法第一个参数是要发送的数据,可以是任何原始类型的数据。

Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)之前,第一个参数必须是一个字符串。

postMessage方法第二个参数可以设置要发送到哪个url,如果当前子页面的url和设置的不一致,则会发送失败,我们设置为*,代表所有url都允许发送。

postMessage方法还有第三个参数,属于高级用法,这里不做讨论,可以稍后去MDN了解。

消息发送到iframePage.html,我们来接收message:

// iframePage.html

//回调函数
function receiveMessageFromIndex ( event ) {
  console.log( 'receiveMessageFromIndex', event )
}

//监听message事件
window.addEventListener("message", receiveMessageFromIndex, false);

我们只需要在子页面监听message事件,并且设置好回调函数即可,来看看打印出来的event:

详解使用postMessage解决iframe跨域通信问题

event对象中的data属性存放着我们从父页面传过来的数据,就这么简单!

让我们再试试从子页面发送数据给父页面:

// iframePage.html

//给父页面发送消息,data为对象
parent.postMessage( {msg: 'MessageFromIframePage'}, '*');

父页面接收数据:

//index.html

//回调函数
function receiveMessageFromIframePage (event) {
    console.log('receiveMessageFromIframePage', event)
}

//监听message事件
window.addEventListener("message", receiveMessageFromIframePage, false);

我看看到,的确可以传输不同的数据,此时data为一个对象:

详解使用postMessage解决iframe跨域通信问题

大家可以到postMessage-demo把代码clone下来运行试试看。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
CSS3截取字符串实例代码【推荐】
Jun 07 HTML / CSS
通过CSS3的object-fit来调整图片适配尺寸的技巧简介
Feb 27 HTML / CSS
详解HTML5中垂直上下居中的解决方案
Dec 20 HTML / CSS
仿CSDN Blog返回页面顶部功能实现原理及代码
Jun 30 HTML / CSS
HTML5 在canvas中绘制文本附效果图
Jun 23 HTML / CSS
整理HTML5中表单的常用属性及新属性
Feb 19 HTML / CSS
HTML5移动端开发中的Viewport标签及相关CSS用法解析
Apr 15 HTML / CSS
HTML5 textarea高度自适应的两种方案
Apr 08 HTML / CSS
HTML里显示pdf、word、xls、ppt的方法示例
Apr 14 HTML / CSS
原生CSS实现文字无限轮播的通用方法
Mar 30 HTML / CSS
position:sticky 粘性定位的几种巧妙应用详解
Apr 24 HTML / CSS
纯CSS3实现div按照顺序出入效果
Jul 15 HTML / CSS
跨域修改iframe页面内容详解
Oct 31 #HTML / CSS
html如何对span设置宽度
Oct 30 #HTML / CSS
关于iframe跨域使用postMessage的实现
Oct 29 #HTML / CSS
使用canvas生成含有微信头像的邀请海报没有微信头像问题
Oct 29 #HTML / CSS
Html5与App的通讯方式详解
Oct 24 #HTML / CSS
html+js 实现markdown编辑器效果
Oct 23 #HTML / CSS
高清屏下canvas重置尺寸引发的问题的解决
Oct 14 #HTML / CSS
You might like
PHP中数据库单例模式的实现代码分享
2014/08/21 PHP
3种php生成唯一id的方法
2015/11/23 PHP
javascript编程起步(第三课)
2007/02/27 Javascript
动态表格Table类的实现
2009/08/26 Javascript
jQuery对象和DOM对象的相互转化实现代码
2010/03/02 Javascript
jQuery 选择器理解
2010/03/16 Javascript
url地址自动加#号问题说明
2010/08/21 Javascript
js下拉框二级关联菜单效果代码具体实现
2013/08/03 Javascript
js获取上传文件大小示例代码
2014/04/10 Javascript
javascript判断css3动画结束 css3动画结束的回调函数
2015/03/10 Javascript
利用JavaScript判断浏览器类型及版本
2016/08/23 Javascript
ReactJs快速入门教程(精华版)
2016/11/28 Javascript
Node.js 中exports 和 module.exports 的区别
2017/03/14 Javascript
Ionic项目中Native Camera的使用方法
2017/06/07 Javascript
layui.js实现的表单验证功能示例
2017/11/15 Javascript
Node.js使用Koa搭建 基础项目
2018/01/08 Javascript
jQuery内容过滤选择器与子元素过滤选择器用法实例分析
2019/02/20 jQuery
vue props 单项数据流实例分享
2020/02/16 Javascript
[01:14]2014DOTA2展望TI 剑指西雅图newbee战队专访
2014/06/30 DOTA
[46:57]EG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python内置的字符串处理函数详细整理(覆盖日常所用)
2014/08/19 Python
Python实现树莓派WiFi断线自动重连的实例代码
2017/03/16 Python
Python图形绘制操作之正弦曲线实现方法分析
2017/12/25 Python
Python爬取个人微信朋友信息操作示例
2018/08/03 Python
python 实现分页显示从es中获取的数据方法
2018/12/26 Python
如何修复使用 Python ORM 工具 SQLAlchemy 时的常见陷阱
2019/11/19 Python
详解Python中第三方库Faker
2020/09/25 Python
python eventlet绿化和patch原理
2020/11/21 Python
如何防止同一个帐户被多人同时登录
2013/08/01 面试题
促销活动策划方案
2014/01/12 职场文书
三分钟演讲稿事例
2014/03/03 职场文书
旅游饭店管理专业自荐书
2014/06/28 职场文书
英文邀请函
2015/02/02 职场文书
导游词之安徽醉翁亭
2020/01/10 职场文书
python 爬取豆瓣网页的示例
2021/04/13 Python
Springboot-cli 开发脚手架,权限认证,附demo演示
2022/04/28 Java/Android