轉(zhuǎn)自:http://blog.csdn.net/lenel
關(guān)于跨域名問題還是問題么,這方面的解決實踐非常多,,今天我就舊話重提把我所知道的通過幾個應(yīng)用場景來分別總結(jié)一下 先說明一點:我說的某某域名在您的控制下的意思是這個域名下的網(wǎng)頁由您來負(fù)責(zé)開發(fā)內(nèi)部的JavaScript 場景一:將bbs.xxx.com的頁面用iframe嵌入到www.xxx.com的中,,如何在iframe內(nèi)外使用js通信 一級域名都是xxx.com 這個域名一定是在您的控制下,所以你只要在兩個頁面中同時升級域名即可 在父窗口和iframe內(nèi)部分別加上js語句:document.domain="xxx.com"; 之后2個頁面就等于在同一域名下,,通過window.parent oIframe.contentDocument就可以相互訪問,,進(jìn)行無障礙的JS通信 在新浪、淘寶等很多頁面都能找到這樣的語句,。不過document.domain不可以隨便指定,只能向上升級,,從bbs.xxx.com升級到肯定會出錯 場景二:將www.的頁面用iframe嵌入到www.xxx.com的中,,兩個域名都在您的控制下,如何在iframe內(nèi)外進(jìn)行一定的數(shù)據(jù)交流 你可以通過相互改變hash值的方式來進(jìn)行一些數(shù)據(jù)的通信 這里的實現(xiàn)基于如下技術(shù)要點: 1,、父窗口通過改變子窗口的src中的hash值把一部分信息傳入,,如果src只有hash部分改變,那么子窗口是不會重新載入的,。 2,、子窗口可以重寫父窗口的location.href,但是注意這里子窗口無法讀取而只能重寫location.href所以要求前提是您控制兩個域 名,,知道當(dāng)前父窗口的location.href是什么并寫在子窗口內(nèi),,這樣通過parent.location.href = "已知的父窗口的href"+"#"+hash。這樣父窗口只有hash改變也不會重載,。 3,、上面兩步分別做到了兩個窗口之間的無刷新數(shù)據(jù)通知,那么下面的來說如何感知數(shù)據(jù)變化,。標(biāo)準(zhǔn)中沒有相關(guān)規(guī)定,,所以當(dāng)前的任意瀏覽器遇到 location.hash變化都不會觸發(fā)任何javaScript事件,也就是說您要自己寫監(jiān)聽函數(shù)來監(jiān)視loaction.hash的值的變化,。做法 是通過setTimeout或者setInterval來寫一個監(jiān)聽函數(shù)每20-100ms查看一下hash是否變化,,如果變化了驅(qū)動js根據(jù)新的數(shù)據(jù)做 想做的事情。 這種實現(xiàn)的一些分析: 1,、信息通道是雙向的,,當(dāng)然會兼容單向,如果只是父窗口向子窗口通知數(shù)據(jù),,只需要子窗口寫hash監(jiān)聽,,反之亦然。 2,、局限性也是頗大,,因為這種通信的前提是雙方知道對方的location.href。如果父窗口帶有動態(tài)的location.search也就是查詢參數(shù),那么子窗口的處理上就比較困難,,需要把父窗口的location.search作為傳遞信息的一部分告知子窗口,。 3、另外的困擾會有瀏覽器帶給你,,IE之外的瀏覽器遇到hash的改變會記錄歷史,,這樣你在處理前進(jìn)后退的時候會非常頭疼 場景三:將www.的頁面用iframe嵌入到www.xxx.com的中,只有被嵌入的在您的控制下,,如何在iframe內(nèi)外進(jìn)行一定的交流 真實場景:google adsence的一個需求,,你希望google發(fā)現(xiàn)您的頁面不能匹配出相關(guān)性非常好的按點擊付費廣告時,你希望google的廣告iframe能夠隱藏,。 google的廣告iframe在google域下顯然不能把自己隱藏掉,,那么怎么辦呢? 1,、google會提供給你一個html頁面 2,、您將這個頁面放置在您的域名下,并告訴google它的位置 3,、當(dāng)google發(fā)現(xiàn)沒有很好的廣告時,,會將子窗口的loaction重定向到您的那個頁面下,這樣您的頁面因為同域名就可以訪問父頁面來隱藏自己了 是不是很巧的方法,? 場景四:您是內(nèi)容發(fā)布商,,如何改造接口,讓其他域名下的頁面可以從瀏覽器端出發(fā)獲得您的數(shù)據(jù) 我們知道ajax的xmlHttpRequest()說到底是一個無刷新請求服務(wù)器數(shù)據(jù)的輔助工具,,但是xmlHttpRequest并不能跨域名請求數(shù)據(jù),,在某些情況下成了極大的限制。 但是我們?nèi)绻ㄟ^其他方式完成無刷新請求數(shù)據(jù)不也可以么,,我們用Dom方法操作動態(tài)JS腳本請求來做這件事,。 //創(chuàng)建一個腳本節(jié)點 var oScript = document.createElement(‘script‘); //指定腳本src src可以指向任意域名 //注意src不再指向靜態(tài)js,而是帶著查詢參數(shù)指向一個動態(tài)腳本廣播服務(wù),。 oScript.src = "http:///query.php?"+yourQueryString; //如果指定了charset 同時還可以解決xmlHttpRequest另一大困擾 亂碼問題 //oScript.charset = "utf-8"; //通過Dom操作把這個新的節(jié)點加入到文檔當(dāng)中 document.getElementsByTagName("head")[0].appendChild(oScript); 這樣只要query.php的輸出是可執(zhí)行的javaScript腳本,,比如:djsCallBack({jsondata}); 當(dāng)他從服務(wù)器返回后就會自動執(zhí)行,你可以方便的用json方式來做數(shù)據(jù)傳遞了。 要注意,,您的腳本請求最好帶上時間戳,,避免瀏覽器緩存造成取回數(shù)據(jù)實時性下降。 如果您是數(shù)據(jù)提供者,,您可以要求數(shù)據(jù)索取者在查詢參數(shù)中提供回調(diào)函數(shù)名,,比如query.php?callback=myDataHandler&key=...? 這樣您就可以根據(jù)參數(shù)來提供給他myDataHandler({jsondata}),這樣不同的數(shù)據(jù)索取者都會得到自定義的正確的異步回調(diào)。 進(jìn)一步發(fā)展,,可以做一個統(tǒng)一的從xml到動態(tài)json的數(shù)據(jù)轉(zhuǎn)化服務(wù)器,,脫離數(shù)據(jù)的實際意義,針對任何xml接口都可以作為轉(zhuǎn)化后提供給客戶端直接訪問。 這樣就不用針對單獨xml數(shù)據(jù)服務(wù),,為了跨域名而做各自的后臺數(shù)據(jù)抓取轉(zhuǎn)化服務(wù),。 用動態(tài)腳本傳數(shù)據(jù)功能非常強大,去年我最先在YAHOO的站點上看到這樣的應(yīng)用,,讓人眼前一亮,。 總結(jié)總結(jié): 第一種場景,相應(yīng)的處理辦法有這非常好的效果,,可以說完全解決了問題,。 第二種場景,相應(yīng)的處理辦法具有一定的跨域數(shù)據(jù)交流功效,,具有相當(dāng)大的局限,,并不適合在復(fù)雜業(yè)務(wù)流程中應(yīng)用,實際上我也確實也沒看到過基于此的大規(guī)模應(yīng)用,。 第三種場景,相應(yīng)的處理辦法比較巧妙,,雖然redirect之后就不干你什么事了,,但如果你是google一樣面向眾多域名的內(nèi)容提供商,也是個不錯的解決思路,。 第四種場景,,相應(yīng)的處理辦法非常強大,對比Ajax可以看到,,跨域名沒問題,,無刷新沒問題,本身又是異步的,,JSON比xml快的多,,同時解決亂碼問題,只是請求都是Get方式的,,不能做Post方式的請求,。多一種武器自然可以從容選擇了。 上面說的基本上都是從前端腳本出發(fā)的各種情景下跨域解決方案,,我們還有一種新式的更強大的武器Flash,,只是現(xiàn)在我還不會用。 |
|