iframe及其跨域通讯方式集合

来源:互联网 发布:maya软件下载中文版 编辑:程序博客网 时间:2024/05/19 09:13

iframe通讯分为两种情况,一个是同域下通讯,另一个是跨域通信

================================================================

先看看同域下父子页面通讯:

我们写两个页面便于比较分析:

父页面parent.html:

<html>

  <head>

    <script type="text/javascript">

      function say() {

        alert("我是父页面方法");

      }

      function callChild(){

        myFrame.window.say();

        myFrame.window.document.getElementById("myInput").value="我变了";

      }

    </script>

  </head>

  <body>

    <input type=button value="调用child.html中的函数say()" onclick="callChild()">

    <iframe name="myFrame" id="child" src="child.html"></iframe>

  </body>

</html>

子页面child.html:

<html>

  <head

    <script type="text/javascript">

      function say(){

        alert("我是子页面方法");

      }

      function callParent() {

        parent.say();

        parent.window.document.getElementsByName("myFrame")[0].style.height="100px";

      }

    </script>

  </head>

  <body>

    <input id="myInput" type=button value="调用parent.html中的say()函数" onclick="callParent()">

  </body>

</html>

这种情况下的通讯比较简单,无非是互相调用方法以及dom元素,操作时候只要分清楚window与document关系就基本ok。

父页面操作子页面方法:

获得对子页面iframe的引用:可以通过两种方式:

1.iframeName.window获得对iframe的window环境操作(于是就可以调用子页面方法或者继续操作子页面元素),上述例子中父页面调用子页面方法以及元素就是通过这种方式进行操作的。

2.iframe.contentWindow跟1的作用是一样的。在上述例子中,我们可以将1中实现方式修改为documnet.getElementById('child').contentWindow.say();

子页面访问父页面:

如果直接操作此时的document以及window环境都是子页面环境,

要想获得父页面数据则需要调用parent.window.method()或者parent.window.document....

同理子页面之间互相访问 都要先访问到父页面 然后靠父页面去调用另一个子页面数据即可。

===================================================================================================

跨域通信(跨文档消息传输):

跨域通信分为两种情况:一种是同主域下不同子域之间跨域,另一种是不同主域之间跨域,先来说第一种:

同主域下不同子域 

举个例子:www.a.com与ajax.a.com之间互相访问其主域都是a.com但是子域不同。这种情况也就会存在跨域问题,解决方法也很简单,只需在需要互相通讯的js中将document.domain设置成相同的主域域名即可:

即document.domain="a.com".然后相互之间就可以像同域下互相访问一样了。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

不同主域下跨域:

方法一:利用iframe的location.hash

举例如下a.com的a.html内包含一个iframe为b.com内的b.html文件。

b.html是可以访问parent的,但由于跨域问题不能访问parent的对象同,理c.html也是可以访问parent的,我们可以通过修改parent.parent.location.hash去通过url进行传参达到我们的访问ifram效果。

不过要注意的是ie、chrome的安全机制无法修改跨域的parent.location.hash,于是我们还要借助于第三个文件去访问(这个文件必须是a.com域名下)就可以达到通过修改hash值进行跨域访问了。

示例如下:

a.com---a.html

<body>

  <iframe src="b.com/b.html"></iframe>

  <script>

  var name=location.hash?location.hash.substring(1):"";

    function doWhat(name){

      alert(name);

    }

  </script>

</body>

b.com---b.html

<body>

  <iframe id='myFrame' src="a.com/c.html"></iframe>

  <script>

    var name="yuchao";

    document.getElementById('myFrame').src=document.getElementById('myFrame').src+"?name="+encodeURL(name);

  </script>

</body>

a.com---c.html

<script>

var name=window.location.href.split('=')[1]

parent.parent.location.hash=name;

</script>

上面a.html要访问子页面b.html(跨域),通过c.html(a.com下)修改其hash值去传参修改parent的parent的hash值,这时候不存在跨域问题,然后根据需要a.html可以定时去检测hash值变化调用实际方法doWhat即可。

这种方式通过hash值去传值虽然可以实现我们跨域效果,不过还是存在几个问题:数据都暴漏在url中,数据容量以及类型都有限制等。。

方法二:利用window.name

详见另篇文章

----------------------------------------------------------------------------------------------------------------------------------------------------------------

html5的postMessage:

HTML5提供了跨文档消息机制(Cross Document Messaging),它提供了跨越frame、tabs或windows通信的能力。使用方法:

otherWindow.postMessage(message, targetOrigin);

otherWindow: 对接收信息页面的window的引用。可以是页面中iframe的contentWindow属性;window.open的返回值;通过name或下标从window.frames取到的值。

message: 所要发送的数据,string类型。

targetOrigin: 用于限制otherWindow,“*”表示不作限制

父页面a.com中的parent.html嵌入b.com的child.html

<html> 

<head>

 <script type="text/JavaScript"> 

   function sendMessage(){ 

     // 通过 postMessage 向子窗口发送数据

     document.getElementById("otherPage").contentWindow 

       .postMessage( 

         document.getElementById("message").value, 

        "http://b.com"

       ); 

   } 

 </script> 

 </head> 

 <body> 

   <iframe src="http://b.com/child.html" 

         id="otherPage"></iframe>

   <input type="text" id="message"><input type="button" 

       value="来自父窗口数据" onclick="sendMessage()" /> 

 </body> 

 </html>
 子页面b.com的child.html

 <html> 

 <head> 
 <script type="text/JavaScript"> 

   window.addEventListener("message", function( event ) { 

     // 把父窗口发送过来的数据显示在子窗口中

     if(event.origin.indexOf('a.com')>-1){

      document.getElementById("content").innerHTML+=event.data+"<br/>";

      event.source.postMessage('得到了消息','*');

     }
      
   }, false ); 

 </script> 

 </head> 
 <body> 

   <div id="content"></div> 

 </body> 

 </html>

 这个小demo是通过在parent中嵌入child,在parent中点击发送按钮利用postMessage进行传输数据,将发送信息发送到iframe(child),child页面通过message事件监听,得到数据才进行后续操作。

从而实现页面之间互相传输数据.message的event有三个属性:

 data:作为第一个参数传递给postMessage的数据;

 origin:发送该消息的窗口协议。域名以及端口号;

 source:发送该消息窗口对象;

 上面demo中在message函数中都演示了每个的用处。