- 蘇格團隊
- 做者:Brady
隨着業務的發展,天然地會有一些公共的業務被抽離成爲公共組件共各個項目使用。可是因爲各個項目用到的技術棧都有所不一樣,因此這個公共組件就不能方便地被引用了。爲解決這個問題,咱們把這個組件寫成了單獨的頁面掛到一個域名下,其餘項目採用iframe或者webview的方式去加載這個頁面,從而實現功能的簡單複用。
不過這過程當中也產生了不少問題,單是跨域就會出現好幾回了。如下我將會介紹我遇到的跨域問題以及一些解決方法。html
爲了保證用戶信息的安全,95年的時候Netscape公司引進了同源策略,裏面的同源指的是三個相同:協議、域名、端口。
違反了同源策略就會出現跨域問題,主要表現爲如下三方面:node
最近在作一個需求,須要用iframe引入一個別人封裝好的相似視頻播放器的東西。iframe裏面有一個全屏的按鈕,點擊後須要頁面讓iframe全屏,因爲受到同源策略的限制,iframe沒法告訴頁面全屏。web
document.domain做用是獲取/設置當前文檔的原始域部分,同源策略會判斷兩個文檔的原始域是否相同來判斷是否跨域。這意味着只要把這個值設置成同樣就能夠解決跨域問題了。
在此我將domain設置爲一級域名的值,a頁面url爲a.demo.com,a頁面中iframe引用的b頁面url爲b.demo.com,具體設置爲ajax
document.domain = 'demo.com'
複製代碼
設置完以後,在a頁面的window上掛載使iframe全屏的方法跨域
// a頁面
window.toggleFullScreen = () => {
// do something
}
複製代碼
在b頁面上能夠直接獲取到a頁面的window對象並直接調用安全
// b頁面
window.parent.toggleFullScreen()
複製代碼
可是這個值的設置也有必定限制,只能設置爲當前文檔的上一級域或者是跟該文檔的URL的domain一致的值。如url爲a.demo.com,那domain就只能設置爲demo.com或者a.demo.com。所以,設置domain的方法只能用於解決主域相同而子域不一樣的狀況。bash
咱們還可使用一個與a頁面同域名但不一樣路由的c頁面做爲中間頁面,b頁面加載c頁面,c頁面調用a頁面的方法,從而實現b頁面調用a頁面的方法。具體操做以下:
在a頁面的node層新開一個路由,此路由加載一個c頁面做爲中間頁面,c頁面的url爲a.demo.com/c。c頁面只是一個簡單的html頁面,在window的onload事件上調用了a頁面的方法。cookie
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
window.onload = function () {
parent.parent.toggleFullScreen();
}
</script>
</body>
</html>
複製代碼
因爲c頁面和a頁面是符合同源策略的,因此能夠避開跨域問題,執行全屏的方法。dom
window.postMessage方法能夠安全地實現跨源通訊,寫明目標窗口的協議、主機地址或端口就能夠發信息給它。post
// b頁面
parent.postMessage(
value,
"http://a.demo.com"
);
複製代碼
// a頁面
window.addEventListener("message", function( event ) {
if (event.origin !== 'http://b.demo.com') return;
toggleFullScreen()
});
複製代碼
爲了安全,收到信息後要檢測下event.origin判斷是否要收信息的窗口發過來的。
經過以上的方法,咱們就能夠和iframe自由通訊啦。