使用postMessage进行react和iframe的数据通信.md
将react的数据传递给iframe
1.首先在父组件(react文件)内引入iframe
<iframe
style={{border:0,width:"100%",height:"100%",}}
src='/model.html'
id='calculation'
//onLoad={this.sendToken}
/>
2.然后在父组件(react文件)内的Button按钮上绑定点击事件
<Button type="primary" onClick={this.handleClick.bind(this)}>点我</Button>
3.继续在父组件(react文件)内编写handleClick方法,使用postMessage传递数据
handleClick = () =>{
//必须是iframe加载完成后才可以向子域发送数据
const childFrameObj = document.getElementById('calculation');
childFrameObj.contentWindow.postMessage(1233, '*'); //window.postMessage
};
4.在iframe页面编写回掉函数并监听message事件
//回调函数
function receiveMessageFromIndex ( event ) {
console.log( '我是iframe,我接受到了:', event.data );
}
//监听message事件
window.addEventListener("message", receiveMessageFromIndex, false);
将iframe的数据传递给react并渲染到页面上
1.在iframe页面编写点击事件,使用postMessage传递数据
<div id="click">点我</div>
<script>
document.getElementById('click').onclick=function(){
parent.postMessage('来自iframe的信息','*'); //window.postMessage
}
</script>
2.在父组件(react文件)的componentDidMount方法中编写接收代码
constructor(){
super();
this.state = {
modelId : '' //1.初始化一个接收数据的变量
};
};
componentDidMount(){ //问题延申:React数据获取为什么一定要在componentDidMount里面调用?
let self = this; //为了避免作用域及缓存
window.receiveMessageFromIndex = function ( event ) {
if(event!=undefined){
console.log( '我是react,我接受到了来自iframe的模型ID:', event.data );
self.setState({
modelId:event.data //2.给变量赋值
})
}
}
//监听message事件
window.addEventListener("message", receiveMessageFromIndex, false);
};
3.将iframe传递过来的数据渲染到组件
<p>来自iframe的模型ID:{this.state.modelId}</p>
到目前为止
react和iframe的通信就告一段落了。
问题延申:React数据获取为什么一定要在componentDidMount里面调用?
1.constructor中获取数据的话,如果时间太长,或者出错,组件就渲染不出来,整个页面都没法渲染了。
2.constructor是作组件state初绐化工作,并不是设计来作加载数据的。
3.如果使用SSR(服务端渲染),componentWillMount会执行2次,一次在服务端,一次在客户端。而componentDidMount不会。
4.constructor可以完成state初始化,componentWillMount使用的很少,目前16版本加入了UNSAFE来标识componentWillMount,新的生命周期static getDerivedStateFromProps()也会替代这个。
5.React16之后采用了Fiber架构,只有componentDidMount声明周期函数是确定被执行一次的,类似ComponentWillMount的生命周期钩子都有可能执行多次,所以不加以在这些生命周期中做有副作用的操作,比如请求数据之类。
6.componentDidMount方法中的代码,是在组件已经完全挂载到网页上才会调用被执行,所以可以保证数据的加载。此外,在这方法中调用setState方法,会触发重渲染。所以,官方设计这个方法就是用来加载外部数据用的,或处理其他的副作用代码。
接下来介绍下 postMessage 这个方法 MDN (需要梯子)
window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数
Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。window.postMessage() 方法被调用时,会在所有页面脚本执行完毕之后(e.g., 在该方法之后设置的事件、之前设置的timeout 事件,etc.)向目标窗口派发一个
MessageEvent消息。 该MessageEvent消息有四个属性需要注意: message 属性表示该message 的类型; data 属性为 window.postMessage 的第一个参数;origin 属性表示调用window.postMessage() 方法时调用页面的当前状态; source 属性记录调用 window.postMessage() 方法的窗口信息。
语法
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
message
将要发送到其他 window的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。
targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。
transfer 可选
是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
message 的属性有:
data
从其他 window 中传递过来的对象。
origin
调用 postMessage 时消息发送方窗口的 origin . 这个字符串由 协议、“
使用postMessage进行react和iframe的数据通信.md的更多相关文章
- React Native & iframe & WebView
React Native & iframe & WebView React Native 怎么渲染 iframe 页面 WebView & source html https: ...
- 封装一个postMessage库,进行iframe跨域交互
这是近期个人在开发chrome插件时的其中一个小总结.还有很多没有总结出来.因为目前插件还在迭代中,(herry菌插件,用于B站C站),属于个人业余的一个小项目.还有很多功能没有实现,以及还需要再看能 ...
- js实现跨域(jsonp, iframe+window.name, iframe+window.domain, iframe+window.postMessage)
一.浏览器同源策略 首先我们需要了解一下浏览器的同源策略,关于同源策略可以仔细看看知乎上的一个解释.传送门 总之:同协议,domain(或ip),同端口视为同一个域,一个域内的脚本仅仅具有本域内的权限 ...
- vue 给嵌套的iframe子页面传数据 postMessage
Vue组件下嵌套了一个不同域下的子页面,iframe子页面不能直接获取到父页面的数据,即使数据存在localStorage中,子页面一样是获取不到的,所以只好使用postMessage传数据: < ...
- vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结
vue—你必须知道的 目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...
- Ipad Safari iframe cookie 当浏览器默认禁用第三方COOKIE
前一阵子,我们发现高版本的Safari中默认会阻止第三方cookie,如下图所示. 问题 什么是第三方cookie呢?在访问一个网站A时,网站A算作第一方,如果网站A中引用了另一个网站X(网站X的域名 ...
- JavaScript 跨域:window.postMessage 实现跨域通信
JavaScript 跨域方式实现方式有很多,之前,一篇文章中提到了 JSONP 形式实现跨域.本文将介绍 HTML5 新增的 api 实现跨域:window.postMessage . 1 othe ...
- html postMessage 创建聊天应用
应用说明: 这个例子演示如何在门户页面以iframe方式嵌入第三方插件,示例中使用了一个来域名下的应用部件,门户页面通过postMessage来通信.iframe中的聊天部件通过父页面标题内容的闪烁来 ...
- html5跨域数据传递(postMessage)
在html5中有个支持跨域传递的方法postMessage,可是实现iframe之间的数据传递! 代码如下:数据发送页面 <!DOCTYPE HTML> <html lang=&qu ...
随机推荐
- 使用IDEA进行打包
使用IDEA打jar包: 1.
- netstat-ll-grep-nohup-df-supervisord
============http://man.linuxde.net/=========== 0 vi / n是查找下一个,alt+n是上一个 u撤销上一步,回到上一步 1. 根据进程号(4974) ...
- sqlserver中一些常用的函数总结
去掉空格方面 LTRIM('内容'):去掉字符串左边的空格 RTRIM('内容'):去掉右边的空格 LTRIM(RTRIM('内容')):去掉字符串左边和右边的空格 REPLACE(‘内容’,' ', ...
- 【前端vue开发】vue开发watch检测的使用
<span style="color:#006600;"><div id="app"> <input type="tex ...
- Linux下LAMP服务器的搭建
1.安装并配置Apache 安装apache的方法有很多种,这里选择通过yum方式进行安装,但需要Linux系统能够连接互联网,执行如下命令,安装Apache. # yum install httpd ...
- ROS二进制日志包 ROS binary logger package
原文网址: 1 http://www.ros.org/news/2017/02/ros-binary-logger-package.html 2 https://github.com/CNR-ITIA ...
- 接口测试工具--Poster与Postman的简单实用
HTTP/SOAP协议接口的功能测试: 1.浏览器URL(GET请求) http://127.0.0.1:8000/login/?username=zhangsan&password=1234 ...
- MIT6.006Lec02:DocumentDistance
MIT6.006是算法导论,Lec02讲的是Document Distance(文档距离),比如比较两个文档相似度或者搜索引擎中都会用到. 计算步骤为: 1.将每个文档分离为单词 2.统计词频 3.计 ...
- CCF CSP 201703-5 引水入城(50分)
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201703-5 引水入城 问题描述 MF城建立在一片高原上.由于城市唯一的水源是位于河谷地带的 ...
- VMware虚拟机Mac OS X无法调整扩展硬盘大小的解决方案
使用VMware虚拟机搭建的MacOSX,在10.10以上可能会出现无法扩充磁盘大小的问题. 因为很多朋友在初次安装MacOSX的时候都默认选择40G的磁盘大小,结果用了没两天之后就发现磁盘不够用了. ...