iframe跨域的幾種常用方法

mosquito發表於2019-04-28

在開發日常中,會遇到使用iframe巢狀其他頁面,想要與巢狀頁面進行互動,常常會涉及打跨域問題,何為跨域?這涉及到同源策略,即協議、埠、域名相同則為同源

違反了同源策略就會出現跨域問題,主要表現為以下三方面:
1.無法讀取cookie、localStorage、indexDB
2.DOM無法獲得
3.ajax請求無法傳送

解決方法

一、設定domain

前提條件:這兩個域名必須屬於同一個基礎域名!而且所用的協議,埠都要一致,否則無法利用document.domain進行跨域

具體實現:

//a.html
 <iframe src="http://b.demo.com:8080/b.html" "load()" id="frame"></iframe>
 <script type="text/javascript">
   document.domain = 'demo.com';
   function load(){
    console.log(frame.contentWindow.name);
   }
 </script>

 //b.html
 <script type="text/javascript">
  document.domain = 'demo.com';
  var name = 'demo';
 </script>

現象:載入a.html,會列印"demo"
原因分析:當主域之間相互通訊的時候,只要將兩者的document.domain賦值為當前的主域地址,即可實現跨域通訊。

二、使用中間頁面

還可以使用一個與a頁面同域名但不同路由的c頁面作為中間頁面,b頁面載入c頁面,c頁面呼叫a頁面的方法,從而實現b頁面呼叫a頁面的方法。具體操作如下:
在a頁面的node層新開一個路由,此路由載入一個c頁面作為中間頁面,c頁面的url為a.demo.com/c。c頁面只是一個簡單的html頁面,在window的onload事件上呼叫了a頁面的方法。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <script>
        window.onload = function () {
            console.log()
        }
    </script>
</body>
</html>

三、postmessage

window.postMessage() 方法允許來自一個文件的指令碼可以傳遞文字訊息到另一個文件裡的指令碼,而不用管是否跨域。一個文件裡的指令碼還是不能呼叫在其他文件裡方法和讀取屬性,但他們可以用這種訊息傳遞技術來實現安全的通訊。

a.html:

<body>
    <button onclick="postTestMessage()">postMessage</button> 
   <iframe src="./b.html" frameborder="0" id="iframe"></iframe> 
</body>
<script>
    let receiveMessage = function(event) {
        console.log('a: ', event);
        let datas = JSON.parse(event.data);
        if (datas.type === "advert") {
                let postIframeData = {
                        type:'adGivePrize',
                        givePrize:true
                };
                //iframe傳送資訊~~~~
                window.frames[0].postMessage(JSON.stringify(postIframeData), '*');
                // window.frames[0].postMessage('a頁面', '*');
        }
    }

    window.addEventListener("message", receiveMessage, false);

    function postTestMessage() {
        let defaultAdData = {
                    type:'advert', 
                    gameData:{
                        adId: '123'
                    }
            };
        window.postMessage(JSON.stringify(defaultAdData), '*');
    }
</script>

b.html

<body>
    <h1>我是b頁面</h1>
</body>
<script>
var receiveMessage = function(event) {
    console.log('b: ', JSON.parse(event.data));
}
window.addEventListener("message", receiveMessage, false);
</script>

在實際使用此方法的過程中遇到了b.html的DOM未載入完就觸發了window.addEventListener(),在b.html接收不到資料,因此在a.html中加了定時器

// 定時訪問傳送資訊,在iframe頁面在沒載入完頁面觸發了addEventListener方法,獲取不到資料
         let count = 0;
     that.timer = setInterval(() => {
       postTestMessage();
       count++;
       if (count > 10) {
         clearInterval(that.timer);
       }
     }, 500);

通過以上方法可以解決iframe跨域問題啦~有錯誤歡迎指正
參考來源:https://juejin.cn/post/684490...

相關文章