如果看懂了前文利用window.name+iframe跨域獲取數據,那麼此文也就很好理解了。一樣都是動態插入一個iframe,然後把iframe的src指向服務端地址,而服務端同樣都是輸出一段js代碼,同樣都是利用和子窗口之間的通信完成數據傳輸,同樣要針對同源策略做出處理。
要理解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文件,然後自己點點超鏈接。沒錯,錨點就是為了能讓文檔滾動到指定的位置,而這個位置由你來定!因為是“滾動”,所以得有滾動條才行,如果木有滾動條那麼不能滾也就不能動了,錨點也就沒用了,仔細想想確實如此。錨點應用很廣,舉個大家都見過的例子,百度百科,裡面的導航使用的就是錨點技術。
我們查看下它的實現代碼,實現也非常的easy
錨點設置是個a標簽,它的href指向內容和跳轉位置的name值一致(其實差個#),需要注意的是如果用的是name,那麼必須用a標簽包裹,而該法在html5中已經被廢除。我們設置錨點通常采用id的方式,更簡單,也不會產生沒用的文檔元素。
說完錨點,我們來說說location.hash。還是在博客園的百科頁面,在導航欄點擊”網站簡介“後,注意這時候地址欄發生了變化!多出來的的正是location.hash值(字符串)。
而location.hash和location.href一樣,既能獲取它的值,也能用它進行重定向(重定位)。繼續留在博客園的百科主頁,然後在控制台輸入location.hash = "#2”,然後頁面就跳轉到”發展歷程“這部分了,和普通的錨點一樣的效果。
而這個過程頁面是不會進行刷新的,但是如果要回到之前的頁面卻能使用浏覽器的前進、後退鍵。
了解了這些基礎知識後,我們就要開始跨域了!
其實很簡單,如果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上傳遞,也就是再嵌套個窗口,使之與祖輩窗口通信,個人認為更復雜了,有興趣的可以試試。
location.hash+iframe法和jsonp以及window.name+iframe一樣,都是雙向的,但是都只能是GET形式,所以數據只能加在url上。
其實window.name和location.hash是異曲同工的,都是用了window下的屬性,畢竟location.hash也是window下的(window.location.hash)。