1.跨域的一个示例

当你需要操作一个内嵌iframe时,如果这个内嵌iframe和打开的网站不在同一个域中,你时常会遇到这样的报错:

Unsafe JavaScript attempt to access frame with URL http:/www.d1.com from frame with URL http://www.d2.com. Domains, protocols and ports must match.

从报错信息中我们可以知道,浏览器是通过域名(domain),协议(HTTP),端口(Port)。也就是说这三点只要有一个不匹配那就是跨域(Cross domain)。

对于跨域,我们通常的解决办法是在原来的域添加一个文件,用该文件作为中间人来实现跨域。也就是说,先发消息到该文件,由该文件再操作同域的HTML。

HTML 5给我们带来了安全的跨域通信接口,即window.postMessage()方法。它方法原型是:

window.postMessage(msg, domain);

我们可以给指定的domain发送msg。而接收msg的iframe只要注册一个监听事件就可以了。我们看示例:

www.d1.com/a.html

<html>

  <head>

    <title>operate the iframe on other domain</title>

    <script>

      function sendMessage(){

        var frm = document.getElementByIdx_x_x("iframe1");

        frm.contentWindow.postMessage("hello","*")

      }

    </script>

  </head>

  <body>

    <input id="send" type="button" onclick="sendMessage()" value="send message" />

    <br />

    <iframe style="width:300px; height:400px;" id="iframe1" src="http://www.d2.com/b.html"></iframe>

  </body>

</html>

我们再看看监听的那个iframe

www.d2.com/b.html

<html>

  <head>

    <title>a frame which receive the message</title>

    <script>

      var OnMessage = function (e) {

        alert(e.data);

      }

      function init() {

        if (window.addEventListener) {                                    // all browsers except IE before version 9

          window.addEventListener("message", OnMessage, false);

        } else {

          if (window.attachEvent) {                                      // IE before version 9

            window.attachEvent("onmessage", OnMessage);

          }

        }

      }

      init();

    </script>

  </head>

  <body>

    <p>a iframe to receive the message</p>

  </body>

</html>

在监听处理函数中我们可以判断具体的那个domain发来的消息。

注意事项

如果你在接受消息的iframe中通过JavaScript来修改DOM元素。要确保iframe已经加载完成,可以这样做:

_overlay = document.getElementByIdx_x_x("iframe1");

if(_overlay.attachEvent){

  _overlay.attachEvent("onreadystatechange", function(){

    if(_overlay.readyState === "complete" || _overlay.readyState == "loaded"){

      _overlay.detachEvent( "onreadystatechange", arguments.callee);

      sendMessage();

    }

  });

} else {

  if(_overlay.addEventListener){

     _overlay.addEventListener( "load", function(){

    this.removeEventListener( "load", arguments.call, false);

    sendMessage();

    }, false);

  }

}

 注意:子框架向父框架发送消息用

window.parent.postMessage({type: 'IndexBack'}, '*');
监听消息类似
posted on 2017-05-26 10:32  出手就帽你  阅读(475)  评论(0编辑  收藏  举报