html5跨域通信之postMessage的用法

不同域名下的文档因为安全问题,不允许相互之间文档的访问,但是有的时候却不得不需要这样的操作。因此我们一般可以采用 window.name,hash,或者jsonp来实现跨域访问。

不过自从html5出来以后,我们又可以多一种实现方式了postMessage,下面就是一个最简单的消息传递的例子,我们要实现的功能是将page1页面中的内容,发送到不同域名下的page2页面,然后page2将对应消息内容展示出来。

下面是几个比较重要的事件属性:

  • source – 消息源,消息的发送窗口/iframe。
  • origin – 消息源的URI(可能包含协议、域名和端口),用来验证数据源。
  • data – 发送方发送给接收方的数据。
    这三个属性是消息传输中必须用到的数据。

首先我们需要两个页面,然后必须分别位于不同的域名下,当然本机肯定要有一个web服务器,接下来就通过修改host来实现不同域名访问

127.0.0.1 www.postmessage1.com127.0.0.1 www.postmessage2.com

主页http://www.postmessage1.com/page1.html 里面嵌套一个iframe框架

<!DOCTYPE html>
<html>
<head><title>Html5 postMessage跨文档通信</title></head>
<body><input type="text" id="text"><input type="button" id="send" value="发送"><iframe id="ifr" src="http://www.postmessage2.com/page2.html"></iframe><script type="text/javascript">var text = document.getElementById('text'),send = document.getElementById('send'),ifr = window.frames[0];//ifr = document.getElementById('ifr').contentWindow;//确保你使用的是iframe的contentWindow属性,而不是节点对象。send.addEventListener('click',function(){//主窗口postMessage发送消息给iframe子窗口。//子窗口通过监听message事件来获得消息ifr.postMessage(text.value,'http://www.postmessage2.com');})</script>
</body>
</html>

iframe框架的src地址为http://www.postmessage2.com/page2.html

<!DOCTYPE html>
<html>
<head><title></title>
</head><script type="text/javascript">//在iframe窗口中监听messages事件,并接收消息window.addEventListener('message',function(event){var div1 = document.getElementById('div1');if(event.origin === 'http://www.postmessage1.com'){div1.innerHTML += event.data +"<br>";}})</script>
<body><h1>我是一个iframe</h1><div id="div1"></div>
</body>
</html>

跟其他很web技术一样,如果你不校验数据源的合法性,那使用这种技术将会变得很危险;你的应用的安全需要你对它负责。window.postMessage就像是PHP相对于JavaScript技术。window.postMessage很酷,不是吗?

双向数据传输也是一样的:

<!DOCTYPE html>
<html>
<head><title>Html5 postMessage跨文档通信</title></head>
<body><input type="text" id="text"><input type="button" id="send" value="发送"><iframe id="ifr" src="http://www.postmessage2.com/postmessage/iframe01.html"></iframe><script type="text/javascript">var text = document.getElementById('text'),send = document.getElementById('send'),// ifr = window.frames[0];ifr = document.getElementById('ifr').contentWindow;window.addEventListener('message', function(ev){if(ev.origin === 'http://www.postmessage2.com'){alert('从'+ ev.origin + '传过来的消息:' + ev.data);}});send.addEventListener('click',function(){//主窗口postMessage发送消息给iframe子窗口。//子窗口通过监听message事件来获得消息ifr.postMessage(text.value,'http://www.postmessage2.com');})</script>
</body>
</html>

另一个页面的代码如下:

<!DOCTYPE html>
<html>
<head><title></title>
</head><script type="text/javascript">//在iframe窗口中监听messages事件,并接收消息window.addEventListener('message',function(event){var div1 = document.getElementById('div1');if (event.origin === 'http://www.postmessage1.com') {div1.innerHTML += "来自窗口" + event.origin + event.data+"<br>"}//像主页面回送消息event.source.postMessage("你好,这里是:" + this.location, event.origin);});</script>
<body><h1>我是一个iframe</h1><div id="div1"></div>
</body>
</html>

2.通道通信

消息通道提供了一个直接,双向浏览上下文之间的通信手段。跟跨文档通信一样,DOM不直接暴露。取而代之,管道每端为端口,数据从一个端口发送,被另一个端口接收,。

消息通道是有用的,特别是跨多个起源的沟通。请考虑以下情形:
人人网上(http://renren.com)嵌入了一个第三方的游戏页面(通过iframe的形式,如“人人餐厅”),同时,这个第三方的游戏页面(http://game.com)又需要从另外一个通讯录网站(http://address.com)获取用户的通讯信息。咋办?

也就是说通讯录站点要发送信息给游戏站点,根据跨文档通信,我们让父页面作为代理(也就是这里的人人网页面)(类似第一个demo)。然而,这种做法意味着通讯录站点需要有和人人网页面一样的信任级别。人人网这个社交站点需要信任每一个请求,或者为我们过滤(应该指:一个一个指定)。

但是,使用通道通信,通讯录站点(http://address.com)和游戏站点(http://game.com)可以直接沟通

MessageChannel和MessagePort对象

当我们创建了一个MessageChannel对象,我们实际上创造了两个相互关联的端口。一个端口保持开放,为发送端。另外一个被转发到其他浏览上下文(被父页面发送到另外一个iframe元素的子页面中)。

var mc = new MessageChannel();

每一个端口就是一个MessagePort对象,包含3个可用方法:

  • postMessage() 通过通道发送消息
  • start() 开始在端口上分派接受的信息
  • close() 关闭端口

MessagePort对象还有onmessage事件属性,可被用来定义事件句柄而不是事件监听。

实例
上面过于术语的东西我自己都看不明白,还是实例好说话。

首先建立三个网站,其中主网站为:http://localhost/test,另外建立两个子网站http://localhost/test1和http://localhost/test2。现在来模拟两个子网站之间的通信过程:

需求:当子网站1被加载完成后,向子网站2发送消息:“(1)我已经等不及了,你好了吗?<br>”,当子网站2接收到消息后,向子网站1返回消息,“(2)你别急呀,马上就好!”。当子网页1接收到子网站2 的消息后,返回给主页面页面对话信息.

子页面1的代码

<!DOCTYPE html>
<html>
<head><title>通道通信子页面iframe01</title>
</head>
<body>
<script type="text/javascript">window.onload = function(){var mc, portMessageHandler;mc = new MessageChannel();portMessageHandler = function(event){alert(event.data);}//向父页面发送消息以及端口port2window.parent.postMessage('(1)我已经等不及了,你好了吗?<br>', 'http://localhost/test1/main.html', [mc.port2]);//定义本页面接收到消息后,应该做的处理mc.port1.addEventListener('message', portMessageHandler, false);//打开本页面的端口,开始监听。。。mc.port1.start();}</script>
</body>
</html>

主页面的代码:

<!DOCTYPE html>
<html>
<head><title>messageChannel通信</title>
</head>
<body><h1>通道通信实例</h1><iframe style="display: none;" src="http://localhost/test1/iframe01.html"></iframe><iframe style="display: none;" src="http://localhost/test2/iframe02.html"></iframe><script type="text/javascript">window.onload = function(){var iframes, messageHandle;iframes = window.frames;messageHandle = function(event){if (event.ports.length > 0) {//如果有接收端口,将接收的端口与消息转发给iframe02iframes[1].postMessage(event.data,'http://localhost/test2/iframe02.html', event.ports);}}//监听第一个页面window.addEventListener('message',messageHandle,false);}</script>
</body>
</html>

子页面2的代码:

<!DOCTYPE html>
<html>
<head><title>通道通信子页面iframe02</title>
</head>
<body>
<script type="text/javascript">window.onload = function(){var messageHandler = function(event){event.ports[0].postMessage(event.data + "(2)你别急呀,马上就好!");}//子页面2接收到消息,并将新的消息转发给子页面1window.addEventListener('message',messageHandler, false);}</script>
</body>
</html>

结果图

上面的demo动用了三个页面:主页面和两个iframe页面。下面说说每个页面都做了些什么:

首先是第一个iframe页面:其任务有三个,

  • 一是创建MessageChannel通道对象;
  • 二是告诉主页面,我加载好了,并把端口传过去;
  • 三是显示发送信息。
//1.创建MessageChannel通道对象
mc = new MessageChannel();//2.二是告诉主页面,我加载好了,并把端口传过去;
window.parent.postMessage('(1)我已经等不及了,你好了吗?<br>', 'http://localhost/test1/main.html', [mc.port2]);//3.显示发送信息
mc.port1.addEventListener('message', portMessageHandler, false);
mc.port1.start();

主页面其任务很简单就一个:告诉第二个iframe页面,端口已经打开了(第一个iframe就可以确定跟第二个iframe通信的端口了)。

// 将端口告诉其他文档
iframes[1].postMessage(event.data,'http://localhost/test2/iframe02.html', event.ports);

最后就是第二个iframe页面。其任务有两个:一是确定接到的消息与端口;二是将post一个新的数据和此端口保持通信了。

// 1. 接到消息与端口
window.addEventListener('message',messageHandler, false);// 2. 与端口建立通道,post一个新的数据
port.postMessage(message);

html5跨域通信之postMessage相关推荐

  1. html5跨域 postmessage,html5跨域通讯之postMessage的用法总结

    postMessagePortal.html 页面代码 复制代码代码如下: 标题 var targetOrigin = "http://22527.vhost20.boxcdn.cn&quo ...

  2. html5跨域通讯之postMessage的用法

    转自:http://www.cnblogs.com/wshiqtb/p/3171199.html postMessagePortal.html 页面代码 <!DOCTYPE html> & ...

  3. H5跨域通信 - window.postMessage

    一.简介 window.postMessage is a method for safely enabling cross-origin communication. Normally, script ...

  4. window.postMessage - 前端跨域通信

    window.postMessage - 前端跨域通信 window.postMessage() 语法 The dispatched event 安全问题 示例 注意 HTMLIFrameElemen ...

  5. 服务端转发html页面,html5关于外链嵌入页面通信问题(postMessage解决跨域通信)

    说起来挺简单的,可以直接去查询postMessage推送和window.addEventListener接收使用方式,能自己搞明白是最好的,本文章也只是记录一下自己的使用方式 使用postMessag ...

  6. 使用window.postMessage实现跨域通信

    JavaScript由于同源策略的限制,跨域通信一直是棘手的问题.当然解决方案也有很多: document.domain+iframe的设置,应用于主域相同而子域不同: 利用iframe和locati ...

  7. HTML5项目笔记8:使用HTML5 的跨域通信机制进行数据同步

    离线应用系统的设计目标就是在网络离线情况下依然可以操作我们的应用系统,并在网络畅通的情况下与服务器进行数据交互. 所以离线应用系统最终会做成类似C/S架构的客户端应用程序.这边基于Chrome或者 S ...

  8. ifrme嵌入外部页面,在外部页面调用本页面方法,window.postMessage实现跨域通信

    项目场景:vue页面开发的系统要继承外部系统页面,并且在外部系统页面调用本系统的方法,这样来看的话肯定会存在跨域的问题,而且直接调用方法的话,也不太安全,后来了解到window.postMessage ...

  9. vue页面内嵌iframe使用postMessage进行跨域通信

    跨域 关于跨域的详细资料:跨域,这里只需要明确什么情况下跨域了(等同于两个url什么情况下是非同源关系). 协议.域名.端口三者有其一不同,就算是跨域,就算是非同源 本地环境模拟 借助phpstudy ...

最新文章

  1. mysql100万数据一键下载csv_使用PHP来导入包含100万条数据的csv文件,请问你最快多久能全部导入mysql 数据库?...
  2. UVa1467 Installations(贪心)
  3. 009_调色盘和高亮样式
  4. 【实战】tensorflow 花卉识别
  5. 关于使用idea工具debug时,断点颜色由红色变成灰色解决方法
  6. fork vfork exit _exit (转)
  7. 对中文语法的编程语言的质疑与回应
  8. 产业链人士:在台积电营收中,第一大客户苹果贡献超过20%
  9. 新型智慧城市建设绘出沈阳“N朵云”
  10. QTP11 5 HP UFT 11 5 下载地址
  11. 2020.9.28 爱客影视3.6.5-pro完整版搭建完毕带解析接口无广告
  12. 台式计算机键盘驱动程序,电脑中使用驱动人生检测不到键盘驱动程序怎么解决...
  13. css 固定宽度超出部分换行,css怎么超出宽度换行
  14. html3d建模,数百个 HTML5 例子学习 HT 图形组件 – 3D 建模篇
  15. win7系统备份还原软件_十分不错的系统还原工具 一键还原备份系统软件 一键还原备份SGIMINI4.0通用版本...
  16. 最后的最后的一场考试
  17. android操作系统偷流量,运营商在“偷流量”?用实验告诉你真相!
  18. pytorch transforms图像增强
  19. 布局文件:报警告 This inspection highlights unknown XML attributes in Android resource files and Andro...
  20. Python3+pygame中国象棋 代码完整 非常好 有效果演示

热门文章

  1. 放弃node-sass,启用sass
  2. “九河下稍天津卫,三道浮桥两道关”,知道嘛意思吗?
  3. 什么是NetBIOS协议
  4. DDD领域模型有必要么?
  5. 这几种放松方法,助你复习效率更佳
  6. 【蜡笔小新全集】+动漫【灌蓝高手】 高速在线看
  7. websocket(通信)和地址获取
  8. sql in 和 exits
  9. openfire日志配置
  10. linux node gyp 编译,node gyp编译所需要的环境