跨域传值即主页面与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操作时间(年-月-日 时-分-秒 星期几)
Jun 20 Javascript
Javascript的数组与字典用法与遍历对象的属性技巧
Nov 07 Javascript
jQuery中复合属性选择器用法实例
Dec 31 Javascript
DOM基础教程之使用DOM控制表格
Jan 20 Javascript
JavaScript 不支持 indexof 该如何解决
Mar 30 Javascript
JS跨域解决方案之使用CORS实现跨域
Apr 14 Javascript
JS 动态加载js文件和css文件 同步/异步的两种简单方式
Sep 23 Javascript
Bootstrap3多级下拉菜单
Feb 24 Javascript
jQuery选择器_动力节点Java学院整理
Jul 05 jQuery
bootstrap是什么_动力节点Java学院整理
Jul 14 Javascript
vue-rx的初步使用教程
Sep 21 Javascript
Vue跨域请求问题解决方案过程解析
Aug 07 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排序算法的复习和总结
2012/02/15 PHP
php读取大文件示例分享(文件操作类)
2014/04/13 PHP
php实现简易聊天室应用代码
2015/09/23 PHP
PHP一个简单的无需刷新爬虫
2019/01/05 PHP
自制基于jQuery的智能提示插件一枚
2011/02/18 Javascript
同一页面多个商品倒计时JS 基于面向对象的javascript
2012/02/16 Javascript
js加载读取内容及显示与隐藏div示例
2014/02/13 Javascript
JavaScript中使用Object.create()创建对象介绍
2014/12/30 Javascript
DEDECMS如何为文章添加HOT NEW标志图片
2015/08/14 Javascript
jquery+ajax实现省市区三级联动效果简单示例
2017/01/04 Javascript
Node.js学习之TCP/IP数据通讯(实例讲解)
2017/10/11 Javascript
详解bootstrap导航栏.nav与.navbar区别
2017/11/23 Javascript
详解angularjs 学习之 scope作用域
2018/01/15 Javascript
浅谈React高阶组件
2018/03/28 Javascript
Angular 封装并发布组件的方法示例
2018/04/19 Javascript
微信小程序实现动态获取元素宽高的方法分析
2018/12/10 Javascript
js实现计算器功能
2020/08/10 Javascript
Vue实现图书管理小案例
2020/12/03 Vue.js
ansible作为python模块库使用的方法实例
2017/01/17 Python
浅谈五大Python Web框架
2017/03/20 Python
Python 结巴分词实现关键词抽取分析
2017/10/21 Python
Python cookbook(字符串与文本)针对任意多的分隔符拆分字符串操作示例
2018/04/19 Python
简单谈谈python基本数据类型
2018/09/26 Python
如何在Django项目中引入静态文件
2019/07/26 Python
Python操作SQLite数据库过程解析
2019/09/02 Python
ubuntu 18.04 安装opencv3.4.5的教程(图解)
2019/11/04 Python
python利用递归方法实现求集合的幂集
2020/09/07 Python
优秀毕业生求职信范文
2014/01/02 职场文书
员工合理化建议书
2014/05/19 职场文书
驾驶员安全责任书范本
2014/07/24 职场文书
小学竞选班长演讲稿
2014/09/09 职场文书
搞笑婚前保证书
2015/02/28 职场文书
运动会宣传语
2015/07/13 职场文书
解除合同协议书范本
2016/03/21 职场文书
《童年》读后感(三篇)
2019/08/27 职场文书
Nginx内网单机反向代理的实现
2021/11/07 Servers