宝哥软件园

JS解决了iframe之间的通讯和自适应高度问题

编辑:宝哥软件园 来源:互联网 时间:2021-09-07

首先,iframe通信分为:域内通信和跨域通信。

第一,同域交流

同域通信指的是http://localhost/demo/iframe/iframea . html下a.html页面的嵌套iframe。

例如,带有iframe src=' http :http://localhost/demo/iframe/iframeb . html ' id=' iframea ' name=' iframea '的b.html页面,这两个页面相互通信。例如,我想在父页面A.html的子页面中调用该函数。我们很容易想到document . getelementbyid(' iframea ')。google下的content window . b();这个方法,其中b是子页面的B.html函数。但是在这个调用下有一个我纠结了很久的问题,那就是既然这样的错误是在Firefox下报告的,那么如下:

b不是函数,但是我在子页中明确定义了这样的函数,那么为什么会报错呢?经过仔细分析和谷歌,我发现有这样一个问题需要理解。当iframe没有加载时,我会通过执行这个js来报告这样的错误,所以我尝试在Firefox下使用函数iframe.onload进行测试,但是它没有报告错误,但是它是正确的,所以我决定是这个问题。所以我想写一个兼容IE和火狐的谷歌,并写一个函数来确保iframe已经加载!实际上,给一个回调函数来调用我们上面的方法。

综合以上思路可以写一个这样的代码:

iframe src=' http :http://localhost/demo/iframe/iframeb . html ' id=' iframeA ' name=' iframeA '/iframe div id=' topName ' topnddddddddddddddame/div脚本函数A(){ alert(' A ');} var iframe=document . getelementbyid(' iframeA ');iframeIsLoad(iframe,function(){ var obj=document . getelementbyid(' iframeA ')。contentWindowobj . b();});函数iframeIsLoad(iframe,callback){ if(iframe . attachevent){ iframe . attachevent(' onload '),函数(){ callback callback();});} else { iframe . onload=function(){ callback callback();}}} /scriptB.html代码如下:

var B=function(){ alert(' B ');}子页面调用父页面的函数非常简单,只要这样做就可以了,window . parent . a();

子页面采用父页面元素的值:window . parent . document . getelementbyid(' top name ')。innerhtml和其他方法。

二:iframe跨域通信。

Iframe跨域访问一般分为两种情况,第一种是同一个主域不同子域的跨域访问。第二个是不同的主域跨域。

1.同一主域下不同子域之间的跨域;您可以通过document.domain设置相同的主域来解决这个问题

假设我在abc.example.com下有一个名为abc.html的页面,页面上嵌套了一个iframe,如下所示:iframesrc=' http:3358def.example.com/demo/def.html' id=' iframe 2 ' style=' display : none;/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=' http :http://def . example.com/demo/def . html ' id=' iframe 2 ' style=' display : none;'/iframe//跨域子页面调用父页面的函数(假设下面的测试函数)document . domain=' example.com ';函数test(){ console . log(1);};Def.html法典如下:

/* *子页面调用父页面的方法*/*/document . domain=' example.com;com ';//window . top . test();window . parent . test();或者这两个页面,我认为父页面调用子页面的以下方法:

A.html法典如下:

/* * 跨域父页想调用子页的的函数*/文档。“domain=”示例。com ';var iframe=document。getelementbyid(' iframe 2 ');iframeIsLoad(iframe,function(){ var obj=iframe。内容窗口;物体。child();});函数iframeIsLoad(iframe,回调){ if(iframe。attachevent){ iframe。attachevent(' onload '),函数(){回调();});} else { iframe。onload=function(){ callback callback();} } }假如现在def.html页面有个儿童函数代码如下:

文件。“domain=”示例。com ';function child(){console.log('我是子页');}就可以跨域调用了不管是子页面调用父页面还是父页面调用子页面。一切好的。

2、 是不同主域跨域;

虽然谷歌有几种方法关于不同主域上的跨域问题有通过位置。哈希方法或者窗口。名称方法或者html5及闪光等等,但是我觉得下面内联框架这种方法值得学习下,

如下图所示:域a.com的页面request.html(即http://a.com/demo/ajax/ajaxproxy/request.html)里面嵌套了一个内联框架指向域b.com(http://b.com/demo/Ajax/Ajax代理/响应。html)的response.html,而response.html里又嵌套了域a.com的proxy.html。

思路:要实现a.com域下的request.html页面请求域b.com下的process.php,可以将请求参数通过全球资源定位器(统一资源定位符)传给response.html,由response.html向process.php发起真正的创建交互式、快速动态网页应用的网页开发技术请求(response.html与process.php都属于域b.com),然后将返回的结果通过全球资源定位器(统一资源定位符)传给proxy.html,最后由于proxy.html和request.html是在同个域下,所以可以在proxy.html利用window.top将结果返回在request.html完成真正的跨域。

好吧,先看看页面结构

a.com域下有:

request.html

proxy.html

b.com域下有:

response.html

process.php

先来看看request.html页面如下:

!DOCTYPE HTMLhtml标题新文档/标题/标题正文p id='结果'这里将会填上响应的结果/p a id=' SendBtn ' href=' JavaScript : void(0)'点击,发送跨域请求/a iframe id=' Serverif ' style=' display : none '/iframe脚本文档。getElementById('sendBtn ').onclick=function(){ var URL=' http://b.com/demo/Ajax/Ajax proxy/reponse。html ',fn=' GetPerson ',//这是定义在response.html的方法reqdata='{'id' : 24} ',//这是请求的参数回调='回调;//这是请求全过程完成后执行的回调函数,执行最后的动作交叉请求(url、fn、reqdata ),回调);//发送请求}函数CrossRequest(url,fn,reqdata,callback){ var server=document。getelementbyid(' Serverif ');server.src=url '?fn=' encodeURIComponent(fn)'数据=' encodeURIComponent(reqdata)'回调=' encodeURIComponent(回调);} //回调函数函数回调(数据){ var str='我的名字是data.name ' .我是一个"数据性"的人。我是"数据。年龄"岁。文件。getelementbyid(' result ').innerHTML=str}/脚本/正文/html这个页面其实就是要告诉response.html:我要让你执行你定义好的方法GetPerson,并且要用我给你的参数{'id' : 24} ' .response.html纯粹是负责将回收这个方法名传递给下一位仁兄proxy.html,而proxy.html拿到了回收这个方法名就可以执行了,因为proxy.html和request.html是同域的。

response.html代码如下:

!DOCTYPE HTMLhtml标题新建文档/标题/标题正文iframe id='proxy'/iframe脚本//通用方法创建交互式、快速动态网页应用的网页开发技术请求function _request (reqdata,url,回调){ var xmlhttpif(窗口. XMLHttpRequest){ xmlhttp=new XMLHttpRequest();} else { xmlhttp=新ActiveX对象(' Microsoft .XMLHTTP’);} xmlhttp。onreadystatechange=function(){ if(xmlhttp。readystate==4 xmlhttp。status==200){ var data=xmlhttp。responsetext回调(数据);} } xmlhttp.open('POST ',URL);xmlhttp。setrequestheader(' Content-Type ',' application/JSON;charset=utf-8 ');xmlhttp。发送(请求数据);} //通用方法获取全球资源定位器(统一资源定位符)参数function _ Getquery(key){ var query=location。href。拆分('?')[1],值=decodeURIComponent(查询。拆分(键'=')[1]。split(" "[0]);返回值;} //向process.php发送创建交互式、快速动态网页应用的网页开发技术请求函数GetPeer(请求数据,回调){ var URL=' http://b.com/demo/Ajax/Ajax代理/进程。PHP ';var fn=函数(数据){ var proxy=文档。getelementbyid(' proxy ');代理人。'http://a.com/demo/ajax/ajaxproxy/Proxy.html?数据=' encodeURIComponent(数据)'回调=' encodeURIComponent(回调);};_请求(reqdata、url、fn);}(function(){ var fn=_ Getquery(' fn '),reqdata=_getQuery('data '),callback=_ Getquery(' callback ');eval(fn '(“请求数据”、“回调”));})();/脚本/正文/html这里其实就是接收来自request.html的请求得到请求参数和方法后向服务器process.php发出真正的创建交互式、快速动态网页应用的网页开发技术请求,然后将从服务器返回的数据以及从request.html传过来的回调函数名传递给proxy.html。

接下来看看服务器端编程语言(专业超文本预处理器的缩写)代码如下,其实就是想返回一个json数据:

?PHP $ data=JSON _ decode(file _ get _ contents(' PHP ://input '));标头('内容-类型:应用程序/JSON;charset=utf-8 ');echo(“{”id“:”).$data-id,”年龄': 24、'性别':'男孩'、'姓名':'黄雪明'});最后就是proxy.html代码:

!DOCTYPE HTMLhtml标题新建文档/标题/标题正文脚本函数_getUrl(键){//通用方法,获取统一资源定位器参数var query=location.href.split('?')[1],值=decodeURIComponent(查询。拆分(键'=')[1]。split(" "[0]);返回值;}(function(){ var callback=_ GetURl(' callback '),data=_ GetURl(' data ');eval('窗口。'顶部'。decodeURIComponent(回调)'(' decodeURIComponent(数据)')'));})();/脚本/正文/html这里也是最后一步了,代理终于拿到了request.html透过response.html传过来的回调函数名以及从response.html直接传过来的响应数据,利用window.top执行request.html里定义的回调函数。

三、iframe高度自适应的问题。

内联框架高度自适应分为2种,一种是同域下自适应另外一种是跨域下自适应,下面我们来看看同域下内联框架高度自适应的问题。

1.同域下内联框架高度自适应的问题:

思路:获取被嵌套内联框架元素,通过Java脚本语言取得被嵌套页面最终高度,然后在主页面进行设置来实现。

假如我们演示有iframe1.html和iframe2.html

下面贴上iframe1.html代码如下:

!DOCTYPE HTMLhtml标题新建文档/标题样式* {边际:0划水:0;}/style/head body iframe src=' http :3358 a.com/demo/Ajax/iframe height/iframe 2。html ' style=' width :100%;border:1px实心# 333;'框架边框=' 0 ' id=' iframe '/iframe脚本窗口。onload=function(){ var iframeid=document。getelementbyid(' iframe ');if(iframeid!窗户。opera){ if(iframeid。内容文档iframeid。内容文档。尸体。offset theight){ iframeid。height=iframeid。内容文档。尸体。偏移光线;}else if(iframeid .文档iframeid .文件。尸体。滚动高度){ iframeid。高度=iframeid .文件。尸体。滚动高度;} } }/script/body/html iframe 2。超文本标记语言

!DOCTYPE HTMLhtml标题新建文档/标题样式* {边际:0划水:0;}/style/head body div style=' height :500 px;'/div /body/html就可以动态设置iframe1页面的高度为iframe2的高度了。

2.跨域下iframe的高度适应性问题。

首先我们知道iframe跨域不能被上面的js控制,所以只能用一个中键。我们可以在b.com域下嵌套一个iframe2.html页面,在a.com域下嵌套一个iframe1.html页面。然后我在iframe2.html页面嵌套了一个和iframe1.html同域的iframe3.html页面,这样iframe1.html和iframe3.html就可以无障碍交流了。因为iframe2.html嵌套在iframe3.html,iframe2.html可以重写iframe3.html的href值。

iframe1中的内容:

Iframe1.html内容主要接受来自iframe3.html页面的内容并完成相应的操作。Iframe1.html法典如下:

iframe src=' http :3358 b.com/demo/Ajax/iframe height/iframe 2 . html ' style=' width :400 px;' height:200px'id='iframe'/iframe脚本var IFR _ El=document . getelementbyid(' iframe ');函数GetFrdata(data){ IFR _ El . style . height=data ' px ';}/content in }/script iframe 2 . html:

Iframe2.html的内容是如何将价值传递到iframe3.html页面。刚才说这个值传递给了iframe3.html页面的href,所以你只需要修改iframe的src。因为不需要刷新C页面,所以可以通过哈希将它传递给iframe3.html页面。iframe2.html法典如下:

!DOCTYPE HTMLhtml标题新建文档/标题样式* { margin:0划水:0;}/style/head body iframe id=' iframe ' src=' http :http://a.com/demo/Ajax/iframe height/iframe 3 . html ' width=' 0 ' height=' 230 px '/iframe脚本var oldHeight=0,IFR _ El=document . getelementbyid(' iframe ');t clearInterval(t);var t=set interval(function(){ var height=document . body . scroll height;if(oldHeight!=高度){ oldHeight=高度;ifr _ el.src=' # ' oldHeight} },200);/script /body/html大家可以看到,默认情况下,我给iframe1.html iframe2.html的高度是200像素,但是在iframe2.html,我给iframe3.html的高度是230像素,所以正常情况下是有滚动条的。所以现在我想得到iframe2.html滚动条的高度,把这个高度传递给经过iframe3.html的src,然后在iframe3.html页面得到这个高度值,再传递给iframe1.html(因为iframe1.html和iframe3.html在同一个域),这样iframe1.html就可以得到这个高度值,然后把自己的高度设置为这个值。

iframe3.html页面的唯一功能是通过href接收来自iframe2.html页面的值,并将其传递给iframe1.html页面,但是来自iframe2.html页面的值可以通过计时器检查,以查看location.href是否更改,但感觉效率低下。另一种方法是通过新浏览器中的onhashchange事件(IE8、Chrome 5.0、Firefox 3.6、Safari 5.0、Opera 10.6)监控href的变化。

Iframe3.html法典如下:

脚本变量oldHeight=0;t clearInterval(t);var t=setInterval(function(){ var height=location . href . split(' # ')[1];如果(身高身高!=old height){ old height=height;if(window . parent . parent . GetFrdata){ window . parent . parent . GetFrdata(old height);} } },200);/script可以解决跨域实现iframe自适应高度的问题。

四.摘要

以上就是本文的全部内容,希望对大家的学习有所帮助。有问题可以留言讨论。

更多资讯
游戏推荐
更多+