每天学习一点点,成功增加一大步

iframe 跨域通信的解决方案

前端 zhanghui 1973℃

一、跨源通信概述

JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:

首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:

对于主域相同子域不同的通信方法这里不一一列举了,这里主要讲解一下跨主域的通信问题。

二、postMessage 的概述

源:协议、端口号(https默认值433)、主机域名(document.domain)
作用:向目标窗口派发MessageEvent消息(四个属性)
兼容参考

MessageEvent四个属性:

1.message(类型)
2.data(window.postMessage的第一个参数)
3.origin(调用postMessage时页面的当前状态)
4.source(调用postMessage的窗口信息)

三、postMessage 语法:

otherWindow.postMessage(message, targetOrigin, [transfer]);
  • otherWindow: 其他窗口(目标窗口)的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames(如父窗口向内嵌的iframe窗口发送信息)
  • message :信息内容,低版本浏览器只支持字符串,高版本可以各种数据都行
  • targetOrigin :目标窗口的源,可以是字符串*表示无限制,或URI,需要协议端口号和主机都匹配才会发送
  • transfer:参考MDN

四、接收postMessage发送的信息MessageEvent

window.addEventListener("message", function(MessageEvent){
  var origin = event.origin || event.originalEvent.origin; 
  ....
  }, false);

五、iframe嵌套父子窗口通信

父窗口:

<!--我是父窗口-->  
<div class="parent" >
      <iframe src="子窗口链接" id="iframe"></iframe>
</div>
<script>
//监听子窗口信息
 window.addEventListener('message',function(event){
   ...
   })
//父窗口给子窗口发消息,
document.getElementByID('iframe').contentWindow.postMessage(msg,'子窗口源');
   
</script>

子窗口:

<!--我是子窗口-->  
<div class="child"></div>
<script>
//子窗口给父窗口发消息
try {//放到trycatch里面,解决有些手机卡住报错问题
  window.top.postMessage(msg,'父窗口源');
      //嵌套一层使用window.top(parent),多层window.frameElement
      //使用top而不是window,top指向iframe最顶层窗口
  } catch (error) {

}

//监听父窗口信息
 window.addEventListener('message',function(event){
   ...
   })
</scrip

注意:
父窗口给子窗口发信息,需要用iframe的contentWindow属性作为调用主体
子窗口给父窗口发的信息需要使用window.top,多层iframe使用window.frameElement

参考:

MDN:postMessage说明
兼容性
html5 postMessage解决跨域、跨窗口消息传递

转载请注明:隨習筆記 » iframe 跨域通信的解决方案

喜欢 (5)