跨域传值即主页面与iframe之间互相传值


Posted in Javascript onDecember 09, 2013

需求一:主页面A 怎么向 iframe B 传递数据呢?

这种方式,是主页面需要给 iframe B 传递数据,然后 iframe B 获得到数据后进行特定的处理

实现方式

实现的技巧就是利用 location 对象的 hash 值,通过它传递通信数据,我们只需要在主页面A中设置 iframe B 的 src 后面多加个 #data 字符串(data就是你要传递的数据),如下图所示:

然后在 iframe B 中通过某种方式能即时的获取到这儿 data 就可以了,其实常用的一种方式就是:

1. 在 iframe B 中通过 setInterval 方法设置定时器, 监听 location.href 的变化即可获得上面的 data 信息
2. 然后 iframe B 就能根据这个 data 信息进行相应的逻辑处理

需求二:iframe B 怎么向 主页面A 传递数据呢?

这种方式,是 iframe B 需要给主页面传递数据,然后主页面根据获得到数据后进行特定的处理

实现方式

实现的技巧就是利用一个代理 IframeC,它嵌入到 iframe B 中,并且和主页面A必须保持是同域,然后我们通过它充分利用上面第一种通信方式的实现原理就能把 iframe B 的数据传递给 iframeC,接下来的问题就是怎么让iframeC把数据传递给主页面A ,如下图所示:

因为,iframeC 和主页面是同域的,所以它们之间传递数据就变得简单多了,我们这里的方式就是使用一个经常使用的属性 window.top (也可以使用window.parent.parent),它返回对载入浏览器得最顶层 window 对象的引用,这样我们就能直接条用主页面A中方法啦,哈哈哈,简单吧。
到此,我们做个简单分析总结

这种实现方式的前提也是最大的缺点就是 iframe 中的内容必须是我们可控的,但是至少我们这种实现方式是建立在浏览器的安全规则之上的,没有破坏应用本身的安全性。
实现时需要考虑的一些细节

尽量考虑到了易用,可扩展性和可维护性,比如:

让第三方 App 只需加载一个我们提供的JS种子文件就能很方便的使用我们为其提供的各种工具
上面的各种工具,我们采用包的形式进行组织,最大化的实现按需加载
第一条中的JS种子文件只提供基础的方法实现,并且把最常用的工具包放在里面,比如高度自适应
通过种子文件,我们还提供给第三方 App 一些常用的JS工具包,而且直接使用的类似YUI3模块的动态加载机制就可使用指定的工具包
对第三方 App 和 主页面传递的数据进行分类(自我调用,登录验证,传递数据等等)
传递的数据使用满足特定规范的JSON格式,并通过统一的服务出口发出去,主页面提供一个统一服务接口解析数据,并根据规范调用相应的方法
还有,就是版本控制的问题,为了尽量减少给第三方App带来影响,以上所有这些JS文件的版本都是采用向后兼容的策略,小版本使用服务器设置SQUID缓存特定频率的失效时间实现,大版本更新根据用户自己的需求手动更改
当然,以上可能不是最优的解决方案,只是希望能给你一些帮助和引导,我们也在逐步的改进我们的一些实现方式,比如版本控制这块儿,我们也有一些问题需要解决

具体的代码

主页面A的源码

Js代码 
/*主页面A*/ 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>主页面A</title> 
<script type="text/javascript"> 
function init(){ 
document.domain = 'bai.sohu.com'; 
alert('我是主框架,嵌入了第三方应用IframeB,下面开始加载应用'); 
var iframeTag = document.getElementById('frameB'), 
iframeSrc = 'http://test.com/iframePage.html'; iframeTag.src = iframeSrc; 
iframeTag.style.display = 'block'; 
}; 
function callback(h){ 
var iframeB = document.getElementById('frameB'); 
alert('IframeC调用我(主框架)接口,把IframeB的高度传给我,具体值是:' + h); 
iframeB.style.height= h + 10 + 'px'; 
iframeB.src += '#'+ h 
}; 
</script> 
</head> 
<body onload="init();"> 
<p>我是主页框架,我的域是:bai.sohu.com</p> 
<iframe id="frameB" style="display:none;"></iframe> 
</body> 
</html>

iframeB(iframePage.html)的源码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>iframeB</title> 
</head> 
<body onload="init();"> 
<p style="height:500px;">我是三方应用,我的域是:test.com</p> 
<iframe id="frameC" style="height:1px;width:1px;display:none;"></iframe> 
</body> 
</html> 
<script type="text/javascript"> 
function init(){ 
alert('我是第三方App,下面开始创建和主框架同域的通信通道IframeC,并设置它的src,用#号传递高度值'); var iframeTag = document.getElementById('frameC'), 
iframeSrc = 'http://bai.sohu.com/iframePageC.html#', 
pageHeight = document.documentElement.scrollHeight || document.body.scrollHeight; 
iframeTag.src = iframeSrc + pageHeight; 
iframeTag.style.display = 'block'; 
window.setTimeout(function(){ 
alert('主页面设置我(IframeB)的src,通过Hash(#)给我传递它收到的高度:' + location.hash); 
},2000); 
}; 
</script>

iframeC(iframePageC.html)的源码
<script type="text/javascript"> 
document.domain = 'bai.sohu.com'; 
alert('我(IframeC)收到iframeB通过参数(#)给我传递高度值,我现在调用主页面方法去设置IframeB的高度'); 
top.callback(window.location.href.split('#')[1]); 
</script>
Javascript 相关文章推荐
JS 巧妙获取剪贴板数据 Excel数据的粘贴
Jul 09 Javascript
javascript数组去重3种方法的性能测试与比较
Mar 26 Javascript
浅析ajax请求json数据并用js解析(示例分析)
Jul 13 Javascript
JavaScript 中的日期和时间及表示标准介绍
Aug 21 Javascript
浅谈利用JavaScript进行的DDoS攻击原理与防御
Jun 04 Javascript
JavaScript计算某一天是星期几的方法
Aug 05 Javascript
JavaScript的ExtJS框架中表格的编写教程
May 21 Javascript
jQuery短信验证倒计时功能实现方法详解
May 25 Javascript
jQuery实现切换隐藏与显示同时切换图标功能
Oct 29 jQuery
axios发送post请求springMVC接收不到参数的解决方法
Mar 05 Javascript
还不懂递归?读完这篇文章保证你会懂
Jul 29 Javascript
vue项目出现页面空白的解决方案
Oct 31 Javascript
深入理解JavaScript中的传值与传引用
Dec 09 #Javascript
js Array操作的最简短最容易理解方法
Dec 09 #Javascript
javascript放大镜效果的简单实现
Dec 09 #Javascript
javascript贪吃蛇完整版(源码)
Dec 09 #Javascript
关于js内存泄露的一个好例子
Dec 09 #Javascript
JS连连看源码完美注释版(推荐)
Dec 09 #Javascript
解析Javascript中难以理解的11个问题
Dec 09 #Javascript
You might like
php关于array_multisort多维数组排序的使用说明
2011/01/04 PHP
php学习笔记 php中面向对象三大特性之一[封装性]的应用
2011/06/13 PHP
一个简单的php加密解密函数(动态加密)
2013/06/19 PHP
PHP简单日历实现方法
2016/07/20 PHP
PHP基于新浪IP库获取IP详细地址的方法
2017/05/04 PHP
PHP多线程模拟实现秒杀抢单
2018/02/07 PHP
Laravel重定向,a链接跳转,控制器跳转示例
2019/10/22 PHP
PHP解决高并发的优化方案实例
2020/12/10 PHP
区分JS中的undefined,null,&quot;&quot;,0和false
2007/03/08 Javascript
在Windows上安装Node.js模块的方法
2011/09/25 Javascript
字符串的replace方法应用浅析
2011/12/06 Javascript
JavaScript版DateAdd和DateDiff函数代码
2012/03/01 Javascript
关于JS管理作用域的问题
2013/04/10 Javascript
基于jquery实现的自动补全功能
2015/03/12 Javascript
简单理解vue中track-by属性
2016/10/26 Javascript
jQuery实现字符串全部替换的方法
2016/12/12 Javascript
浅谈JS函数节流防抖
2017/10/18 Javascript
基于vue配置axios的方法步骤
2017/11/09 Javascript
微信小程序wx:for和wx:for-item的用法详解
2018/04/01 Javascript
小程序实现带年月选取效果的日历
2018/06/27 Javascript
10分钟彻底搞懂Http的强制缓存和协商缓存(小结)
2018/08/30 Javascript
[45:15]Optic vs VP 2018国际邀请赛淘汰赛BO3 第一场 8.24
2018/08/25 DOTA
[01:11:46]DOTA2-DPC中国联赛 正赛 iG vs Magma BO3 第一场 2月23日
2021/03/11 DOTA
使用python绘制人人网好友关系图示例
2014/04/01 Python
python使用xlrd与xlwt对excel的读写和格式设定
2017/01/21 Python
Jupyter安装nbextensions,启动提示没有nbextensions库
2020/04/23 Python
python 将list转成字符串,中间用符号分隔的方法
2018/10/23 Python
彻底解决Python包下载慢问题
2020/11/15 Python
python 实现端口扫描工具
2020/12/18 Python
2014入党积极分子批评与自我批评思想报告
2014/10/06 职场文书
2014年科室工作总结
2014/11/20 职场文书
毕业论文答辩开场白和答辩技巧
2015/05/27 职场文书
运动会200米广播稿
2015/08/19 职场文书
浅谈redis整数集为什么不能降级
2021/07/25 Redis
python数字图像处理:图像的绘制
2022/06/28 Python
如何使用注解方式实现 Redis 分布式锁
2022/07/23 Redis