转载

利用location.hash+iframe跨域获取数据详解

前言

如果看懂了前文 利用window.name+iframe跨域获取数据 ,那么此文也就很好理解了。一样都是动态插入一个iframe,然后把iframe的src指向服务端地址,而服务端同样都是输出一段js代码,同样都是利用和子窗口之间的通信完成数据传输,同样要针对同源策略做出处理。

location.hash和锚点

要理解location.hash+iframe跨域获取数据的机制,先得知道什么是location.hash,楼主买一送一,把锚点也一起介绍了。

其实锚点很简单,也相信大家都有用过。纳尼,你布吉岛?小看段代码就略知一二了(代码效果 猛戳这里 ):

<a href='#1'>red</a> <a href='#2'>black</a> <a href='#3'>yellow</a> <a href='#4'>pink</a> <div id='1' style='width:500;height:200;background-color:red'> </div> <div id='2' style='width:500;height:200;background-color:black'> </div> <div id='3' style='width:500;height:200;background-color:yellow'> </div> <div id='4' style='width:500;height:1200;background-color:pink'> </div>

保存为html文件,然后自己点点超链接。没错,锚点就是为了能让文档滚动到指定的位置,而这个位置由你来定!因为是“滚动”,所以得有滚动条才行,如果木有滚动条那么不能滚也就不能动了,锚点也就没用了,仔细想想确实如此。锚点应用很广,举个大家都见过的例子,百度百科,我们打开博客园词条的百科-> 博客园 ,里面的导航使用的就是锚点技术。

利用location.hash+iframe跨域获取数据详解

我们查看下它的实现代码,实现也非常的easy

利用location.hash+iframe跨域获取数据详解

利用location.hash+iframe跨域获取数据详解

锚点设置是个a标签,它的href指向内容和跳转位置的name值一致(其实差个#),需要注意的是如果用的是name,那么必须用a标签包裹,而该法在html5中已经被废除。我们设置锚点通常采用id的方式,更简单,也不会产生没用的文档元素。

说完锚点,我们来说说 location.hash 。还是在博客园的百科页面,在导航栏点击”网站简介“后,注意这时候地址栏发生了变化!多出来的的正是location.hash值(字符串)。

利用location.hash+iframe跨域获取数据详解

利用location.hash+iframe跨域获取数据详解

而location.hash和location.href一样,既能获取它的值,也能用它进行重定向(重定位)。继续留在博客园的百科主页,然后在控制台输入location.hash = "#2”,然后页面就跳转到”发展历程“这部分了,和普通的锚点一样的效果。

利用location.hash+iframe跨域获取数据详解

利用location.hash+iframe跨域获取数据详解

而这个过程页面是不会进行刷新的,但是如果要回到之前的页面却能使用浏览器的前进、后退键。

如何跨域

了解了这些基础知识后,我们就要开始跨域了!

其实很简单,如果index页面要获取远端服务器的数据,动态插入一个iframe,将iframe的src属性指向服务端地址。这时top window和包裹这个iframe的子窗口是不能通信的(同源策略),所以改变子窗口的路径就行了,将数据当做改变后的路径的hash值加在路径上,然后就能通信了(和window.name跨域几乎相同),将数据加在index页面地址的hash值上。index页面监听地址的hash值变化(html5有hashchange事件,用setInterval不断轮询判断兼容ie6/7),然后做出判断,处理数据。

<body>   <script type="text/javascript">     function getData(url, fn) {       var iframe = document.createElement('iframe');       iframe.style.display = 'none';       iframe.src = url;        iframe.onload = function() {         fn(iframe.contentWindow.location.hash.substring(1));         window.location.hash = '';         document.body.removeChild(iframe);       };        document.body.appendChild(iframe);     }      // get data from server     var url = 'http://localhost:8080/data.php';     getData(url, function(data) {       var jsondata = JSON.parse(data);       console.log(jsondata.name + ' ' + jsondata.age);     });   </script> </body>
<?php   // 如果有必要则进行数据处理 $_GET['..']   // code      // 返回的数据   $data = '{/"name/":/"hanzichi/",/"age/":10}';    echo    "   <script>     window.location = 'http://localhost:81/location-hash/proxy.html' + '#' + /"$data/";   </script>   " ?>

服务端文件中重定向的地址和index页面需同源,这是通信的关键。

然后在网上找了些别人写的博客,基本都是加个第三方代理文件,原理是一样的,服务端部分新建个iframe,然后将数据附加在location.hash上传递,也就是再嵌套个窗口,使之与祖辈窗口通信,可以参考 js中各种跨域问题实战小结(二) - 大额_skylar ,个人认为更复杂了,有兴趣的可以试试。

总结

location.hash+iframe法和jsonp以及window.name+iframe一样,都是双向的,但是都只能是GET形式,所以数据只能加在url上。

其实window.name和location.hash是异曲同工的,都是用了window下的属性,毕竟location.hash也是window下的(window.location.hash)。

参考

正文到此结束
Loading...