首先说明下,iframe通信 分为:同域通信 和 跨域通信。
一、 同域通信
所谓同域通信是指 下的a.html页面嵌套 iframe
比如: <iframe src="https://localhost/demo/iframe/iframeB.html">的B.html页面,这两个页面数据进行通信,比如我想在父页面A.html 调用子页面当中的函数 我们很容易想到或者google下 document.getElementById('iframeA').contentWindow.b(); 这种方法,其中b 是子页面B.html中的一个函数。但是这样调用下有个问题我纠结了很久,就是既然在火狐下报这样的错误, 如下:
b不是个函数 但是我在子页面明明定义了这么一个函数,那么为什么会报这样的错误呢?经过仔细分析及google,发现有这么一个问题需要理解,当iframe没有加载完成后 我就去执行这个js会报这样的错误,所以就试着在火狐下 用iframe.onload 这个函数 进行测试,果然没有报错,是正确的 所以就确定是这个问题。所以就想写个兼容IE和火狐 google写个函数 来确定iframe已经加载完成!,其实给个回调函数来调用我们上面的方法。
综合上面的思路 就可以写个这样的代码:
<iframe src="https://localhost/demo/iframe/iframeB.html"></iframe> <div>topNddddddddddddddddame</div> <script> function A(){ alert("A"); } var iframe = document.getElementById('iframeA'); iframeIsLoad(iframe,function(){ var obj = document.getElementById('iframeA').contentWindow; obj.b(); }); function iframeIsLoad(iframe,callback){ if(iframe.attachEvent) { iframe.attachEvent('onload',function(){ callback && callback(); }); }else { iframe.onload = function(){ callback && callback(); } } } </script>
B.html 代码如下:
var b = function(){ alert("B"); }
子页面调用父页面的函数很简单,只要这样搞下就ok了,window.parent.A();
子页面取父页面元素的值: window.parent.document.getElementById("topName").innerHTML等方法。
二: iframe跨域通信。
iframe跨域访问一般分为2种情况,第一种是同主域,不同子域的跨域。 第二种是:不同主域跨域。
1、 是同主域下面,不同子域之间的跨域;可以通过document.domain 来设置相同的主域来解决。
假如现在我有个域 abc.example.com 下有个页面叫abc.html, 页面上嵌套了一个iframe 如下:<iframe src="https://def.example.com/demo/def.html" ></iframe>,我想在abc域下的页面abc.html 访问 def域下的def.html 我们都知道由于安全性 游览器的同源策略的限制,js不能操作页面不同域下 不同协议下 不同端口的页面,所以就要解决跨域访问了,假如父页面abc.html 页面有个js函数:function test(){console.log(1);}; 我想在子页面调用这个函数 还是按照上面的同域方式调用 parent.test();这样,通过在火狐下看 已经跨域了 解决的办法是 在各个js函数顶部 加一句 document.domain = 'example.com',就可以解决了。
abc.html代码如下:
<iframe src="https://def.example.com/demo/def.html"></iframe> // 跨域 子页调用父页的 函数 (假设是下面test函数) document.domain = 'example.com'; function test(){console.log(1);};
def.html代码如下:
/* * 子页调用父页的方法 */ document.domain = 'example.com'; //window.top.test(); window.parent.test();
还是这两个页面 我想父页调用子页 如下方法:
a.html代码如下:
/* * 跨域 父页想调用子页的的函数 */ document.domain = 'example.com'; var iframe = document.getElementById('iframe2'); iframeIsLoad(iframe,function(){ var obj = iframe.contentWindow; obj.child(); }); function iframeIsLoad(iframe,callback){ if(iframe.attachEvent) { iframe.attachEvent('onload',function(){ callback && callback(); }); }else { iframe.onload = function(){ callback && callback(); } } }
假如现在def.html页面有个child函数 代码如下:
document.domain = 'example.com'; function child(){console.log('我是子页');}
就可以跨域调用了 不管是子页面调用父页面 还是父页面调用子页面。一切ok!
2、 是不同主域跨域;
虽然google有几种方法关于不同主域上的跨域问题 有通过location.hash方法或者window.name方法或者html5及flash等等,但是我觉得下面iframe这种方法值得学习下,
如下图所示:域a.com的页面request.html(即)里面嵌套了一个iframe指向域b.com()的response.html,而response.html里又嵌套了域a.com的proxy.html。