只要是足够大的web项目,一定会遇到iframe跨域的情况,而且问题就在于,跨域后,iframe中如何触发父页面的回调呢?
别告诉我用设置document.domain的方式,因为这个非常不靠谱,而且还会造成一连串的跨域解决问题,只要一个页面设置了domain,该页面嵌入的所有iframe都必须设置domain,才能进行相互访问,否则,非常悲剧。
这里,我们不谈domain,我们说说别的解决方案:iframe+iframe。下面来举个例子。
1、假定http://www.baidufe.com/cmt是专门用来进行评论管理的页面:A,在A页面上定义了回调方法:callback,需要在评论提交完成后执行,并将相关数据回传给callback
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"> <title>评论管理</title> <script type="text/javascript"> var callback = function(cmtData){ // TODO }; </script> </head> <body> <iframe src="#" frameborder="0" id="cmtIframe" name="cmtIframe"></iframe> <form action="http://cmt.baidufe.com" target="cmtIframe"> ... </form> </body> </html>
2、评论信息会提交到http://cmt.baidufe.com域下进行处理:B,假设B页面的内容是这样:
<script type="text/javascript"> parent.callback({isDelete:1}); </script>
仔细分析一下,这已经发生跨域了,cmt.baidufe.com是www.baidufe.com的子域,对于iframe来说,这依然是有跨域限制的。要想在cmt.baidufe.com下访问www.baidufe.com的对象,是无法做到的。
那应该怎么解决?
再分析下,既然在iframe为cmt.baidufe.com的页面下无法访问父页面www.baidufe.com下的对象,那么就是说,浏览器会认为域名不相同,所以不允许js交互。
好,如果把iframe改为www.baidufe.com的页面下,那么就避开了这个问题,就一定能访问到父页面为www.baidufe.com下的对象。这样也就不会存在跨域的问题了。
究竟该怎么实际操作呢?
改变http://cmt.baidufe.com的内容即可:
<iframe src="http://www.baidufe.com/proxy?isDelete=1" frameborder="0"></iframe>
是的,iframe中,再套一层iframe,这个内层iframe指向一个和父页面相同域名的代理文件,并将参数传递下去。
最后处理回调的问题,就可以完全交给这个代理文件了,代理文件可以这么写:
<script type="text/javascript"> var s = (location.hash || location.search).substr(1).split('&'); top.callback(isDelete:s[1]); </script>
是的,其实就这么简单,这样就能非常完美的实现,form表单+iframe跨域时的回调处理。
关于这个代理文件,其实可以写的非常完善,这里就先不弄了,后续有时间再补上!