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

摘要:
==hash){  varaction=...;  vardata=...;  window.parent.parent[action];}},1);存在问题:data长度限制,在chrome,ff,safari等浏览器中hash长度限制有50K以上,但是在ie下最多2000左右的限制。
实现方案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
varframeurl ="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
varcurrentHash = location.hash;
setInterval(function(){
varhash = location.hash.substring(1);
if(currentHash!==hash){
  varaction = ...;
  vardata = ...;
  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
varcurrentHash = location.hash;
setInterval(function(){
varhash = location.hash.substring(1);
if(currentHash!==hash){
  varaction = ...;
  vardata = ...;
  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
vardata={.....};
childFunc.func1(data,function(result){
//result即为child.html中执行func1后的结果值
});

child.html:

1
2
3
4
5
6
7
8
9
varfunc1 =function(data,callback){
//对data的一些操作
varresult = ...;
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
vareventIndex=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
varcurrentHash = location.hash;
setInterval(function(){
varhash = location.hash.substring(1);
if(currentHash!==hash){
  varaction = ...;
  vardata = ...;
varcallback=....;//应该是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){
    varcallback =//hash.callback
    varcallbackData =//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
variframe = document.getElementById("childFrame").contentWindow;
varmsg = {data:parentData,action:childFunc,callback:/*类似于上面的方法myEventIndex*/}
varchildDomain ="http://www.child.com"
iframe.postMessage(msg,childDomain);
1
2
3
4
5
6
window.addEventListener("message",function(obj){
vardata = obj.data;
varaction = data.action;
vardata = 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){
vardata = obj.data;
varaction = data.action;
vardata = data.data;
varcallback = data.callback;
childFuncClass[action](data,function(result){
vard = {action:callback,data:result};
varparentDomain="http://www.parent.com";
window.parent.postMessage(d,parentDomain);
});
});

免责声明:文章转载自《Iframe父子窗口之间的跨域事件调用和传值》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇vscode: Visual Studio Code 常用快捷键WSDL4J解析WSDL文件方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

postman 发送post请求,参数为json

mvc 控制器接收post请求,参数为json PostMan设置 Headers设置key和Value值 key:Content-Type,Value:application/json。 参数设置: 选中Body并进行参数设置,选择raw,格式为json。就酱 控制器代码: //post 请求测试 [HttpPost] //请求方法,...

MYSQL管理----数据库删除恢复

(1) 如果备份了,就好解决了。略。 (2)如果日志打开,使用mysqlbinlog来恢复。 mysqlbinlog工具的使用,大家可以看MySQL的帮助手册。里面有详细的用,在这个例子中,重点是--start-position参数和--stop-position参数的使用。•--start-position=N从二进制日志中第1个位置等于N参量时的事件开...

InfluxDB学习之InfluxDB的HTTP API查询操作

    本文我们再来介绍下使用InfluxDB的HTTP API进行数据查询操作的过程。 一、说明 官方文档上介绍说,使用HTTP API进行查询是比较初级的一种方式。推荐使用第三方语言库和客户端管理程序进行查询操作。 二、InfluxDB进行HTTP API查询方法 使用HTTP API在InfluxDB进行查询主要是发送 GET 请求到 Influx...

UVM中的class--2

1)uvm_component从uvm_report_object继承而来,提供的功能包括: 1)Hierarchy,-----searching and traversing component hierachy 2)Phasing-----调用uvm_phase以及预先定义的很多phase 3)config-------调用config_db的m...

vue+elementui搭建后台管理界面(6登录和菜单权限控制)

不同的权限对应不同的路由(菜单),同时侧边栏也根据权限异步生成,实现登录和鉴权思路如下: 登录:点击登录,服务器验证通过后返回一个 token ,然后存到 cookie,再根据 token 拉取用户权限 鉴权:通过 token 获取对应的roles, 计算有权限的路由,使用 router.addRoutes 动态加载路由 数据和操作通过 vuex 进行...

layer弹出层框架alert与msg详解

layer至今仍作为layui的代表作,她的受众广泛并非偶然,而是这五年多的坚持,不断完善和维护、不断建设和提升社区服务,使得猿们纷纷自发传播,乃至于成为今天的Layui最强劲的源动力。目前,layer已成为国内最多人使用的web弹层组件,GitHub自然Stars3000+,官网累计下载量达30w+,大概有20万Web平台正在使用layer。    ...