从前面的一篇文章中,我们知道HTML5 PostMessage不支持IE8以下的浏览器跨域,于是我想到了window.name支持ie6和ie7的方案,那么能否把这两种合并起来,给出一种全兼容的跨域方案呢?还别说,真有人能做到。来自:三水清
html5 postMessage实现跨域
postMessage是html5的一个新功能,可以实现不同域名之间的通信,通过给postMessage方式发送数据,监听则通过在父子窗口添加onmessage事件进行。
缺点也就很明显了,只有支持html5的浏览器才支持这种跨域方式,像IE6、7当然就拒之门外了!
window.name实现跨域
window.name实现跨域也是一个比较老的问题,之前kejun写过一个demo,可是给的却是同域名的通信。
其实kejun的实例中就是实现跨域的,不过他采用了同一个域名,而且过程比较崎岖:
- 建立iframe,指定src为被跨域的页面
- 被跨域文件修改window.name,将数据传给window.name
- 将iframe.src修改为本域代理文件,然后就可以取到contentWindow.name
- 进行处理数据,清除iframe
充分的运用了window.name因为页面的url改变而name不改变的特性。
但是如果我们是自己用,还是可以的,而如果我们放出去要别人使用我们写的东西,那样学习成本太大。
多浏览器双向跨域
为了解决上面的问题,我们使用的方法就是如果支持postMessage的浏览器就使用postMessage,如果不支持的就采用window.name的方式,幸运的是在IE6、7中支持跨域设置window.name,而我们就可以简单的通过window.name来跨域。然后建立计时器来监听window.name是否发生了变化,如果变化则接收并分析window.name,然后做请求。
演示和代码
<body> <div style="width:100%;border:1px solid green;"> <h3>this page from :<span id="host"></span></h3> <input type="text" value="" id="data" /><button id="btn" onclick="send();">提交</button> </div> <iframe id="iframeA" src="http://1.qdemo.sinaapp.com/cross-domain/client.html" style="border:1px solid #ff6600;width:100%;height:300px;"></iframe> <script type="text/javascript"> document.getElementById('host').innerHTML = location.host; function send(){ var val = document.getElementById('data').value; sendMessage(val); } (function(win, doc){ var ifr = doc.getElementById('iframeA').contentWindow; var cb = function(json){ alert(location.host+" get msg:"+json); }; var sendMessage = function(){ if(win.postMessage){ if (win.addEventListener) { win.addEventListener("message",function(e){ cb.call(win,e.data); },false); }else if(win.attachEvent) { win.attachEvent("onmessage",function(e){ cb.call(win,e.data); }); } return function(data){ ifr.postMessage(data,'*'); }; }else{ var hash = ''; setInterval(function(){ if (win.name !== hash) { hash = win.name; cb.call(win, hash); } }, 50); return function(data){ ifr.name = data; }; } }; win.sendMessage = sendMessage(); })(window, document); </script> </body>
<body> <h3>this page from :<span id="host"></span></h3> <input type="text" value="" id="data" /><button id="btn" onclick="send();">提交</button> <ul> <li>firefox、chrome等高级浏览器采用html5 postMessage方法</li> <li>IE6 7等使用window.name方法</li> <li>支持双向跨域,在chrome 13、firefox6、IE6+测试通过</li> <li>window.name可以通过data加随机数方式,避免两次提交的数据相同,本例没做处理,所以如果不改变value值点击提交是不会触发alert的</li> <li><a href="cross-domain.zip">demo下载</a></li> </ul> <script type="text/javascript"> document.getElementById('host').innerHTML = location.host; function send(){ var val = document.getElementById('data').value; sendMessage(val); } (function(win, doc){ var ifr = win.parent; var cb = function(json){ alert(location.host+" get msg:"+json); }; var sendMessage = function(){ if(win.postMessage){ if (win.addEventListener) { win.addEventListener("message",function(e){ cb.call(win,e.data); },false); }else if(win.attachEvent) { win.attachEvent("onmessage",function(e){ cb.call(win,e.data); }); } return function(data){ ifr.postMessage(data,'*'); }; }else{ var hash = ''; setInterval(function(){ if(win.name!==hash){ hash = win.name; cb.call(win,hash); } },50); return function(data){ ifr.name = data; }; } } win.sendMessage = sendMessage(); })(window, document); </script> </body>
基于上面的代码,结合我上篇文章的演示,我们再来给出一个iframe自适应高度的解决方案。