首要要做配置操作,配置两个域名,我这里使用的是Apache。附件中的demo1和demo2
<VirtualHost *:80> DocumentRoot "D:/htdocs/iframe/demo1" ServerName www.iframe1.cn </VirtualHost> <VirtualHost *:80> DocumentRoot "D:/htdocs/iframe/demo2" ServerName www.iframe2.cn </VirtualHost>
iframe的一些属性介绍:
属性 | 值 | 描述 |
align | left right top middle bottom |
不赞成使用。请使用样式代替。 规定如何根据周围的元素来对齐此框架。 |
frameborder | 1 0 |
规定是否显示框架周围的边框。 |
height | pixels % |
规定 iframe 的高度。 |
longdesc | URL | 规定一个页面,该页面包含了有关 iframe 的较长描述。 |
marginheight | pixels | 定义 iframe 的顶部和底部的边距 |
marginwidth | pixels | 定义 iframe 的左侧和右侧的边距。 |
name | frame_name | 规定 iframe 的名称 |
sandbox | "" allow-forms allow-same-origin allow-scripts allow-top-navigation |
启用一系列对 <iframe> 中内容的额外限制。 可以在这里做调试 |
scrolling | yes no auto |
规定是否在 iframe 中显示滚动条。 |
1、iframe无刷新文件上传
这个上传我服务器端使用的是PHP代码。
<div style="padding:20px"> <h1>1、无刷新上传</h1> <form action="action.php" enctype="multipart/form-data" method="post" target="iframeUpload"> <iframe name="iframeUpload" width="400" height="400" frameborder='1'></iframe><br/> <input id="file1" name="file1" type="file"> <input value="上传图片" type="submit"> </form> </div>
使用iframe上传的关键点是target="iframeUpload",这个属性的设置。action.php中的代码如下:
<?php require_once('upload.php'); header("Content-Type:text/html;charset=utf-8"); $type = array('jpg', 'jpeg', 'png', 'gif'); $path = sprintf('%s/%s/%s/', date('Y'), date('m'), date('d')); $upload = new App_Util_Upload('file1', 0, $type); //获取上传信息 $info = $upload->getUploadFileInfo(); $fileName = time() . rand(1000, 9999) . '.' . $info['suffix']; $fullName = $path . $fileName; $path = rtrim('upload', DIRECTORY_SEPARATOR) . '/' . $fullName; $success = $upload->save($path); $msg = $success ? '上传成功<br/>' : '上传失败<br/>'; echo $msg; echo '<img src="'.$path.'" width="300" height="300"/>';
2、iframe自适应高度
同域的情况下:
网络中的方法一:直接用onload函数获取iframe中的内容高度,如果页面载入一次以后,高度不变,这招是挺好用的,但是我在firefox与IE中,表现不理想,如图,并没有完全的将页面显示,chrome和safrai的表现不错。
<iframe id="iFrame1" name="iFrame1" width="100%" onload="this.height=iFrame1.document.body.scrollHeight" frameborder="0" src="autoheight.html" scrolling="no"></iframe>
后面发现,如果在iFrame1.document.body.scrollHeight的后面在加上20的话,iframe也是能完全展现出来的,这个应该是受到了我autoheight.html这个页面里的CSS影响,
autoheight.html中的页面代码是这样的:
1 <div style="padding:20px;border:1px solid #000;width:650px"> 2 <img src="autoheight.jpg" width="600"><br/> 3 一张图片 4 </div>
为了验证我的猜想,我把padding给去除掉,还是用原先的代码onload="this.height=iFrame1.document.body.scrollHeight",但事实与我的猜想完全不同
网络中的方法二:这个函数出自于前端开发博客。与上面的简单方法不同,这里多了些浏览器兼容方面的检验。
<script type="text/javascript"> function setIframeHeight(iframe) { if (iframe) { var iframeWin = iframe.contentWindow || iframe.contentDocument.parentWindow; if (iframeWin.document.body) { iframe.height = iframeWin.document.documentElement.scrollHeight || iframeWin.document.body.scrollHeight; } } }; window.onload = function () { setIframeHeight(document.getElementById('iFrame2')); }; </script> <iframe id="iFrame2" name="iFrame2" width="100%" frameborder="0" src="autoheight.html" scrolling="no" onload="setIframeHeight(this)"></iframe>
var iframeWin = iframe.contentWindow || iframe.contentDocument.parentWindow;
这句是用来获取iframe的window对象。
文章Iframes, onload, and document.domain中 说“he iframe element object has a property called contentDocument that contains the iframe’s document object, so you can use the parentWindow property to retrieve the window object.”
意思就是一些浏览器可以通过iframeElement.contentDocument.parentWindow获得iframe的window对象。经过测试发只有IE9与IE8是根据iframe.contentDocument.parentWindow来获取的,其他firefox、chrome、safrai、IE6、IE7都是根据frame.contentWindow获取的
iframe.height = iframeWin.document.documentElement.scrollHeight || iframeWin.document.body.scrollHeight;
这句话就是在获取iframe的高度了。
body是DOM对象里的body子节点,即 <body> 标签;
documentElement 是整个节点树的根节点root,即<html> 标签;
刚刚上一个方法由于用的是body.scrollHeight导致了各个浏览器的解释不同,引起了显示的不一致。经测试发现使用documentElement.scrollHeight后,都能正确显示。
异域的情况下:
跨域的时候,由于js的同源策略,父页面内的js不能获取到iframe页面的高度。需要一个页面来做代理。总共有三张页面,
注意下三个页面的域名
http://www.iframe1.cn/index.html
http://www.iframe1.cn/agent.html
http://www.iframe2.cn/iframe.html
index.html与agent.html在同一个域名下
iFrame3与iframeC分别为index.html与iframe.html页面上面的iframe的id。下面的图是用websequencediagrams在线画的。
index.html中代码:
<iframe id="iFrame3" name="iFrame3" src="http://www.iframe2.cn/iframe.html" width="100%" height="0" scrolling="no" frameborder="0"></iframe>
iframe.html中代码:
<body> <img src="koala.jpg" /> 跨域访问! <iframe id="iframeC" name="iframeC" width="0" height="0" style="display:none;" ></iframe> <script type="text/javascript"> function sethash(){ hashH = document.documentElement.scrollHeight; urlC = "http://www.iframe1.cn/agent.html"; document.getElementById("iframeC").src=urlC+"#"+hashH; } window.onload=sethash; </script> </body>
agent.html中代码:
<body> <script type="text/javascript"> function pseth() { var iObj = parent.parent.document.getElementById('iFrame3'); iObjH = parent.parent.frames["iFrame3"].frames["iframeC"].location.hash; iObj.style.height = iObjH.split("#")[1]+"px"; } pseth(); </script> </body>
3、iframe跨域通信
网络方法一:这是一种通过第三张页面来跨域执行函数,一种代理的感觉
注意下三个页面的域名
http://www.iframe1.cn/index_cross.html
http://www.iframe1.cn/cross_domain2.html
http://www.iframe2.cn/cross_domain1.html
index.html与cross_domain2.html在同一个域名下
iFrame4与iframeD分别为index_cross.html与cross_domain1.html页面上面的iframe的id。
这是一种非常优雅的方式,但是是用url的方式在传递参数,大小被受到了限制,如果数据量大的话,是会有问题的。
index_cross.html中代码:
<script type="text/javascript"> function showQueryString(prompt) { document.getElementById('testCross1').innerHTML = '跨域'+prompt; }; </script> <iframe id="iFrame4" name="iFrame4" src="http://www.iframe2.cn/cross_domain1.html"> </iframe> <div id="testCross1"></div>
cross_domain1.html中代码:
<body> <iframe id="iframeD" name="iframeD" src="http://www.iframe1.cn/cross_domain2.html?cross=success"></iframe> </body>
cross_domain2.html中代码:
<body> <script type="text/javascript"> function getQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; } parent.parent.showQueryString(getQueryString('cross')); </script> </body>
成功后出现的提示信息
网络方法二:
1) 支持HTML5的浏览器可以使用postMessage
IE8、IE9、firefox、chrome和safrai可用postMessage函数
index_cross.html中代码:
<script type="text/javascript"> window.onload = function () { if(window.postMessage) { var ifr = document.getElementById('iFrame5'); var targetOrigin = 'http://www.iframe2.cn/'; //postMessage的第一个参数不仅仅可以是字符串,结构对象、数据对象(如:File和ArrayBuffer)或是数组都是可以 //但IE8/IE9/FireFox3.6及其以下版本只支持字符串数据 ifr.contentWindow.postMessage('I am parent!', targetOrigin); } }; </script>
post_message.html中代码:
<body> <div id="postmessage"></div> <script type="text/javascript"> window.onmessage = function(event){ var event = event || window.event; if (event.origin == 'http://www.iframe1.cn') { document.getElementById('postmessage').innerHTML = event.data; } } </script> </body>
2) IE6、IE7可以用navigator对象的跨大域漏洞
index_cross.html中代码:
<iframe id="iFrame6" name="iFrame6" src="http://www.iframe2.cn/navigator.html" width="100%" height="100"></iframe> <div id="testCross2"></div> <script type="text/javascript"> window.onload = function () { navigator.a = function(prompt) { document.getElementById('testCross2').innerHTML = '这是父页面的方法:'+prompt; }; var iframe = document.getElementById('iFrame6'); if(typeof navigator.b === 'function') { navigator.b('children'); } }; </script>
navigator.html中代码:
<body> <div id="navigator"></div> <script type="text/javascript"> navigator.b = function(prompt) { document.getElementById('navigator').innerHTML = '这是子页面的方法:'+prompt; } setInterval(function(){ if(typeof navigator.a === 'function') { navigator.a('parent'); } }, 3000); </script> </body>
源码可以在这里下载: