Iframe父子窗口之间的跨域事件调用和传值

实现方案1:location.hash传值

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

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

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

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

 

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

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

parent.html:

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

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

child.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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:

1
2
3
4
5
6
7
var  data={.....};
 
childFunc.func1(data, function (result){
 
//result即为child.html中执行func1后的结果值
 
});

  

child.html:

1
2
3
4
5
6
7
8
9
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:

1
2
3
4
5
6
7
8
var  eventIndex=0;
childFunc.func1 =  function (data,callback){
     if ( //callback是function类型){
         //此时window是parent页面的对象
         window[ "myEvent" +eventIndex] = callback;<br>
         childIframe.hash= "action=...&data=...&callback=myEvent" +eventIndex;<br>
     }
};   

  

child.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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:

1
2
3
4
5
6
7
8
9
10
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

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

  

child.html

1
2
3
4
5
6
7
8
9
10
11
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);
     });
});

转载于:https://www.cnblogs.com/ylyw/p/7687726.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值