zoukankan      html  css  js  c++  java
  • Iframe父子窗口之间的跨域事件调用和传值

    实现方案1:location.hash传值

    父页面:parent.html(所在域:www.parent.com)

    子页面:child.html(所在域:www.child.com)

    要实现父子页面双向的事件调用和传值,需要多加一个代理页面,主要用于子页面调用父页面的方法

    代理页面:proxy.html(所在域:www.parent.com)必须与父页面在同域下

    父页面调用子页面方法(即事件通过父页面发起,在子页面中执行):

    父页面中直接设置iframe的src中的hash值

    parent.html:

    var frameurl = "http://www.child.com/child.html"
    document.getElementById("frameId").src=frameurl+"#action="+actionName+"&data="+dataJSONStr;

    子页面中设置定时器监听hash的变化,监听到后直接执行该方法

    child.html:

    var currentHash = location.hash;
    
    setInterval(function(){
    
    var hash = location.hash.substring(1);
    
    if(currentHash!==hash){
    
      var action = ...;
    
      var data = ...;
    
      childFuncClass[action](data);
    
    }
    
    },1);

    同样可以使用onhashchange事件监听到

    子页面调用父页面方法(事件通过子页面发起,在父页面中执行)

    在子页面child.html中添加一个iframe链接到上面所说的proxy.html,child.html中通过改变proxy.html的hash值,在proxy.html中监听hash变化事件,监听到以后直接调用parent.html中的方法(与父页面调用子页面方法一致)

    proxy.html:

    var currentHash = location.hash;
    
    setInterval(function(){
    
    var hash = location.hash.substring(1);
    
    if(currentHash!==hash){
    
      var action = ...;
    
      var data = ...;
    
      window.parent.parent[action](data);
    
    }
    
    },1);
    

      

    存在问题:

    data长度限制,在chrome,ff,safari等浏览器中hash长度限制有50K以上,但是在ie下最多2000左右的限制。

    回调函数的处理

    通常情况下父页面在调用子页面的方法时会有一些回调函数(函数是在parent.html中编写和执行,但是需要child.html中的方法执行完成后再执行,有些情况下会需要child.html中执行的结果)

    比如(通常情况下会做接口的封装):

    parent.html:

    var data={.....};
    
    childFunc.func1(data,function(result){
    
    //result即为child.html中执行func1后的结果值
    
    });
    

      

    child.html:

    var func1 = function(data,callback){
    
    //对data的一些操作
    
    var result = ...;
    
    callback&&callback(result);
    
    }
    

      

    如果出现这种情况的话parent.html中定义的匿名回调函数是不可能以字符串的形式传递到child.html中去的,并且也无法在child.html中再去执行父页面的回调函数

    解决方法:

    在接口封装的时候将回调函数保存下来,通过一个唯一的函数名传递到child.html中,child.html中的方法执行完成后将该函数名传递到proxy.html中执行该函数

    以上面的func1为例

    parent.html:

    var eventIndex=0;
    childFunc.func1 = function(data,callback){
        if(//callback是function类型){
            //此时window是parent页面的对象
            window["myEvent"+eventIndex] = callback;
    childIframe.hash="action=...&data=...&callback=myEvent"+eventIndex;
    } };

      

    child.html:

    var currentHash = location.hash;
    
    setInterval(function(){
    
    var hash = location.hash.substring(1);
    
    if(currentHash!==hash){
    
      var action = ...;
    
      var data = ...;
          
       var callback=....;//应该是myEvent+index
    
      childFuncClass[action](data,function(result){
        proxyIfram.src.hash="action="+callback+"&data="+result;
      });
    
    }
    
    },1);
    

      

    proxy.html:

    setInterval(function(){
    
      if(//hash changed){
    
        var callback  = //hash.callback
        var callbackData = //hash.callbackData
        window.parent.parent[callback](callbackData);
      }
    
    },1);
    

      

    实现方案2:window.postMessage方法

    由于方案1中对ie兼容性有问题(所有ie版本,包括ie11和edge都存在这个问题),方案2使用postMessage方法,该方法理论上对数据量没有限制(猜的),并且对ie可用

    同样是使用iframe嵌入,

    parent.html

    var iframe = document.getElementById("childFrame").contentWindow;
    var msg = {data:parentData,action:childFunc,callback:/*类似于上面的方法myEventIndex*/}
    var childDomain = "http://www.child.com"
    iframe.postMessage(msg,childDomain);
    window.addEventListener("message",function(obj){
        var data = obj.data;
        var action = data.action;
        var data = data.data;
        parentFuncClass[action](data);
    });

      

    child.html

    window.addEventListener("message",function(obj){
        var data = obj.data;
        var action = data.action;
        var data = data.data;
        var callback = data.callback;
        childFuncClass[action](data,function(result){
              var d = {action:callback,data:result};
              var parentDomain="http://www.parent.com";
              window.parent.postMessage(d,parentDomain);
        });
    });
    

      

    真的是坑啊,把方案1中的坑都走过后才找到方案2的方法

  • 相关阅读:
    1104 Sum of Number Segments (20 分)(数学问题)
    1092 To Buy or Not to Buy (20 分)(hash散列)
    1082 Read Number in Chinese (25 分)(字符串处理)【背】
    1105 Spiral Matrix (25 分)(模拟)
    初识网络安全及搭建网站(内网)
    HTML5开发者需要了解的技巧和工具汇总(转)
    native+web开发模式之web前端经验分享
    移动平台3G手机网站前端开发布局技巧汇总(转)
    Asp.net 中图片存储数据库以及页面读取显示通用方法详解附源码下载
    使用H3Viewer来查看VS2010的帮助文档
  • 原文地址:https://www.cnblogs.com/lycnblogs/p/7687255.html
Copyright © 2011-2022 走看看