(2年前舊文,歷來沒發表過,最近從新整理了一下代碼,弄了個steamer-cross)html
原文地址前端
差很少2年前,因爲業務須要,瞭解各類各樣不一樣的跨域方式。但因爲各類方式千奇百怪,我以爲有必要將各類方法封裝起來,方便使用,弄了個簡單的跨域使用庫,裏面包含各類跨域的使用函數,都存放在steamer-cross v1.0分支裏。但2年事後,IE8如下的瀏覽器已經逐漸淡出市場,基本上跨域的方案能夠由postMessage一統天下,因而在MessengerJS啓發下,本身寫了一個steamer-cross v2.0版本,更靈活的用法,且兼顧父子窗口之間互相傳遞數據。git
v1.0版本可能有bug,僅供學習參考,v2.0已寫測試樣例,能夠test
文件夾中看到,文檔不清楚的地方,也能夠參考test/index.html
的寫法。github
本主不會詳細述說各類方法的具體實現,具體的辦法能夠點擊後文參考資料裏面的三篇文章。本文只會說起實現過程當中的一些坑,以及框架的實現辦法。具體的實現方法,能夠參考steamer-cross v1.0版本中的文件,各類辦法的實現,能夠看對應文件夾裏面的文件。ajax
這是最直觀的辦法,只須要一個頁面,在頁面內包含一個指向數據頁面的script tag,而後在src後面多加一個回調函數便可以獲取數據。json
這個辦法先後端都涉及,所以前端的同窗須要後端的配合。其實質只是一個ajax,能夠接收除了post和get以後的其它服務器請求例如put。後端須要修改的是.htaccess文件。加入如下一句後端
Header set Access-Control-Allow-Origin *複製代碼
符號*表明接收任意的HTTP請求,你也能夠經過修改,限制接受請求的域名或者IP地址。跨域
另一個隱藏坑是,ie10如下的瀏覽器是不支持的。值得注意的是,ie8和ie9是經過XDomainRequest來進行CORS通訊的。XDomainRequest一樣支持get和post方法。對象詳細內容請見參考資料。瀏覽器
XDomainRequest的另外一個坑是,當發送POST請求的時候,沒法設置Header,如安全
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");複製代碼
這可能致使後臺無法辨認POST數據。若是是PHP的話,後臺須要特殊的處理,例如
if(isset($HTTP_RAW_POST_DATA))
{
parse_str($HTTP_RAW_POST_DATA, $output);
echo json_encode($output);
}複製代碼
CORS支持狀況:Chrome 4 , Firefox 3.5 , IE 8~9(XDomainRequest), IE 10+ , Opera 12 , Safari
這個辦法坑比較多,網上的辦法會有些問題。這個辦法須要三個頁面,分別是主調用頁(index.html), 數據頁(data.html),和代理頁(proxy.html)。實質的結構是,index.html裏有一個iframe指向data.html,而data.html裏又有一個iframe指向proxy.html。要注意的是,index.html和proxy.html主域和子域都相同,只有data.html是異域,所以當data.html生成數據時,將數據放在proxy.html連接的hash(#)後面,而後再由proxy.html裏的代碼經過parent.parent這樣的調用,將數據放到proxy.html的祖父index.html的連接上面。
大多數教程都是停留在這一步。這是不夠的,還須要在index.html裏面設置一個setInterval去監聽index.html中#的變化,進而獲取數據。聽說有些高端瀏覽器裏面能夠直接用hashchange來監聽,但低端的話最好仍是用setInterval。所以框架裏面用setInterval實現。
因爲window.name在iframe的src的變化時不會改變,因此這個辦法也能夠用於跨域。這個方式雖然也須要跟location.hash也須要三個頁面,但proxy.html的做用很是次要。因爲data.html可以直接對window.name寫值,所以寫值完畢後,只須要將src改爲與index.html主域和子域一致的頁面,就可讓index.html直接調用了。也有不須要proxy頁面的寫法,將iframe的src寫成"about:blank;"就能夠了。
這個辦法對於主調用頁(index.html)和數據頁(data.html)而言是雙向的,即兩個頁面均可以獲得對方的數據(主要是DOM元素)。實質就是index.html包含一個指向data.html的iframe,而後在data.html中改變document.domain,使之和index.html的document.domain是同樣的,這樣就可使兩個頁面互相調用對方的數據。惟一的缺點是隻能應用於子域不一樣,但主域相同的兩個頁面。
網上大部份教程都只教從index.html傳數據到data.html。其實data.html也能夠發數據到index.html。實現方法同樣,只要在data.html裏面發送的地址跟index.html的地址同樣就能夠了。不然瀏覽器會報錯。這是比較優秀的一個辦法,缺點是舊式瀏覽器並不支持。
這是ie6和ie7的一個安全bug。目前彷佛尚未補丁打上,因此主頁面和iframe頁面之間能夠自由調用。