只要是足够大的web项目,一定会遇到iframe跨域的情况,而且问题就在于,跨域后,iframe中如何触发父页面的回调呢?
别告诉我用设置document.domain的方式,因为这个非常不靠谱,而且还会造成一连串的跨域解决问题,只要一个页面设置了domain,该页面嵌入的所有iframe都必须设置domain,才能进行相互访问,否则,非常悲剧。
这里,我们不谈domain,我们说说别的解决方案:iframe+iframe。下面来举个例子。
1、假定http://www.baidufe.com/cmt是专门用来进行评论管理的页面:A,在A页面上定义了回调方法:callback,需要在评论提交完成后执行,并将相关数据回传给callback
<!DOCTYPE HTML>
<htmllang="en-US">
<head>
<metacharset="UTF-8">
<title>评论管理</title>
<scripttype="text/javascript">
var callback = function(cmtData){
// TODO
};
</script>
</head>
<body>
<iframesrc="#"frameborder="0"id="cmtIframe"name="cmtIframe"></iframe>
<formaction="http://cmt.baidufe.com"target="cmtIframe">
...
</form>
</body>
</html>
2、评论信息会提交到http://cmt.baidufe.com域下进行处理:B,假设B页面的内容是这样:
<scripttype="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的内容即可:
<iframesrc="http://www.baidufe.com/proxy?isDelete=1"frameborder="0"></iframe>
是的,iframe中,再套一层iframe,这个内层iframe指向一个和父页面相同域名的代理文件,并将参数传递下去。
最后处理回调的问题,就可以完全交给这个代理文件了,代理文件可以这么写:
<scripttype="text/javascript">
var s = (location.hash || location.search).substr(1).split('&');
top.callback(isDelete:s[1]);
</script>
是的,其实就这么简单,这样就能非常完美的实现,form表单+iframe跨域时的回调处理。
关于这个代理文件,其实可以写的非常完善,这里就先不弄了,后续有时间再补上!