这种方法比上面两种稍微繁琐一点,原理如下:
www.a.com下的a.html想和www.b.com下的b.html通信(在a.html中动态创建一个b.html的iframe来发送请求);
但是由于“同源策略”的限制他们无法进行交流(b.html无法返回数据),于是就找个中间人:www.a.com下的c.html(注意是www.a.com下的);
b.html将数据传给c.html(b.html中创建c.html的iframe),由于c.html和a.html同源,于是可通过c.html将返回的数据传回给a.html,从而达到跨域的效果。
三个页面之间传递参数用的是location.hash(也就是www.a.html#sayHello后面的’#sayHello’),改变hash并不会导致页面刷新(这点很重要)。
具体代码如下:
www.a.com/a.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //通过动态创建iframe的hash发送请求 function sendRequest(){ var ifr = document.createElement( 'iframe' ); ifr.style.display = 'none' ; //跨域发送请求给b.html, 参数是sayHello document.body.appendChild(ifr); } //获取返回值的方法 function checkHash() { var data = location.hash ? location.hash.substring(1) : '' ; if (data) { //处理返回值 alert(data); location.hash= '' ; } } //定时检查自己的hash值 setInterval(checkHash, 2000); window.onload = sendRequest; |
www.b.com/b.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | function checkHash(){ var data = '' ; //模拟一个简单的参数处理操作 switch (location.hash){ case '#sayHello' : data = 'HelloWorld' ; break ; case '#sayHi' : data = 'HiWorld' ; break ; default : break ; } data && callBack( '#' +data); } function callBack(hash){ // ie、chrome的安全机制无法修改parent.location.hash, // 所以要利用一个中间的www.a.com域下的代理iframe var proxy = document.createElement( 'iframe' ); proxy.style.display = 'none' ; // 注意该文件在"www.a.com"域下 document.body.appendChild(proxy); } window.onload = checkHash; |
www.a.com/c.html
1 2 3 4 5 | //因为c.html和a.html属于同一个域, //所以可以改变其location.hash的值 //可通过parent.parent获取a.html的window对象 parent.parent.location.hash = self.location.hash.substring(1); |
可能有人会有疑问,既然c.html已经获取了a.html的window对象了,为何不直接修改它的dom或者传递参数给某个变量呢?
原因是在c.html中修改 a.html的dom或者变量会导致页面的刷新,a.html会重新访问一次b.html,b.html又会访问c.html,造成死循环……囧呀~
所以只能通过location.hash了。这样做也有些不好的地方,诸如数据容量是有限的(受url长度的限制),而且数据暴露在url中(用户可以随意修改)……
html5中有个很酷的功能,就是跨文档消息传输(Cross Document Messaging)。新一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。
使用方法如下:
1 | otherWindow.postMessage(message, targetOrigin); |
说明:
www.a.com/a.html中的代码:
html:
1 |
script:
1 2 3 4 5 6 | window.onload = function () { var ifr = document.getElementById( 'ifr' ); // 若写成'http://www.c.com'就不会执行postMessage了 ifr.contentWindow.postMessage( 'sayHello' , targetOrigin); }; |
www.b.com/b.html的script
1 2 3 4 5 6 7 8 | //通过message事件来通信,实在太爽了 window.addEventListener( 'message' , function (e){ // 通过origin属性判断消息来源地址 e.data== 'sayHello' ) { alert( 'Hello World' ); } }, false ); |
由于本人对flash不怎么熟悉,此处暂时忽略之~
行文至此,突然在口碑网UED博客上看到了一篇 《跨域资源共享的10种方式》,对跨域的多种方法都有介绍(虽然有源码,但多数都是直接调用YUI库的,比较难看出原理)。
里面提到了Cross Frame这种方法,似乎挺不错的,改日一定翻源码来研究。
研究了几天,虽然对多种跨域方法都有所了解了,但是真要投入应用还是明显不够的(还是需要借助一些js库)。
每种方法都有其优缺点,使用的时候其实应该将多种跨域方法进一步封装一下,统一调用的接口,利用js来自动判断哪种方法更为适用 。
联系客服