iframe 父子頁面之間的通信

作為一個沒有什么情懷和追求的前端工程師, 是么有怎么考慮過 iframe 用法的, (畢竟從學習到工作自己扮演的一直是"前端小妹妹"的角色, 這種臟活累活一般是交給后端臭屌絲的,直到公司的全棧妹子來找我探討這個跨域通信的問題);

真是不看不知道, 一看嚇一跳. 原來 iframe 也存在跨域的問題. 跨域和不跨域情況下和父級頁面的通信方式也是略有不同.

文中示例代碼均在github

同域情況下的父子頁面通信方式

show you the demo

父級頁面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>   
  <script>
    function say() {
      console.log("i am father page");
    }

    function callChild() {
      mySon.window.say();
      mySon.window.document.getElementById('button').innerHTML = '調用結束';
    }
  </script>
  <button id="button" onclick="callChild()"> 調用兒子的方法 </button>
  <iframe name="mySon" src="http://localhost:3000/demo.html?aim=xiaopang" frameborder="0"></iframe>
</body>
</html>

兒子頁面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>

  <script>
    function say() {
      console.log('i am child page');
    }
    function callFather() {
      parent.say();
      parent.window.document.getElementById('button').innerHTML = '調用結束'
    }
  </script>

  <button id="button" onclick="callFather()"> 調用爸爸的方法 </button>
</body>
</html>

以上示例功能

  • 調用函數:

    1. 父級頁面調用子頁面的函數 name.window.func();
    2. 子頁面調用父級頁面的函數 parent.window.func();
  • 訪問頁面元素
    window都拿到了,元素不會拿。請自行百度。

ps: 注意事項:

兒子頁面加載完成后再進行訪問, 判斷方法:

  1. iframe 上添加 onload 事件;
  2. document.readyState == 'complete';

跨域情況下父子頁面通信的方法

如果 iframe 所鏈接的是外部的頁面, 尼瑪, 居然有跨域限制, 有跨域限制, 有跨域限制......

父頁面向子頁面傳遞數據

跨域情況下的父子頁面通信的原理大概就是使用 hash / 直接傳參數搞定;傾向于hash;

  1. 在子頁面中通過定時器監聽 location.hash 的變化就能夠拿到父級頁面傳來的數據啦;
  2. 一次性的從父頁面 get 過來的參數中提取有用的部分,就 OK 啦;

子頁面向父頁面傳遞數據

跨域情況下,子頁面向父頁面傳遞數據的實現原理是使用一個代理的 iframe (就像是跨域請求中的代理服務器一樣), 并且保持代理的子頁面和父級頁面是同域的此時就可以通過, window.top 或者 window.parent.parent 就可以獲取父級頁面的引用啦. 嗶哩嗶哩...

不 bb 上 demo

父級頁面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
   我是彩筆圈圈

   <script>
     var i = 1;
     function say(data) {
       console.log('我是爸爸' + data);
     }

     function add() {
       document.getElementById('quanquan').setAttribute('src', 'http://localhost:3000/demo2.html?aim=quanquan#'+ ++i)
     }

   </script>
   <button onclick="add()">+1</button>
   <iframe id='quanquan' src="http://localhost:3000/demo2.html?aim=quanquan#1" frameborder="0"></iframe>
</body>
</html>

子級頁面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <script>
    var hash = location.hash, i = 1;
    function checkData() {
      if(hash !== location.hash) {
        hash = location.hash
        console.log('我是兒子' + hash);
      } 
    }
    function say() {
      console.log('i am child page');
    }
    function callFather() {
      document.getElementById('quanquan').setAttribute('src', 'http://localhost:4000/proxy.html#'+ ++i)
    }
    setInterval(checkData, 1e3);
  </script>
  <button id="button" onclick="callFather()"> 調用爸爸的方法 </button>
  <iframe id="quanquan" style="display: none" src="http://localhost:4000/proxy.html#1" frameborder="0"></iframe>
</body>
</html>

proxy 中轉頁面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>proxy</title>
</head>
<body>
  <script>
    var hash = location.hash;
    function callGrandFather(data) {
      window.top.say(data);
    };
    function checkData() {
      if ( hash !== location.hash ) {
        callGrandFather(location.hash);
        hash = location.hash;
      }
    }
    setInterval(checkData, 1e3);
  </script>
</body>
</html>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協議...
    w_zhuan閱讀 532評論 0 0
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協議...
    他在發呆閱讀 830評論 0 0
  • 前言 原文地址:前端跨域總結 博主博客地址:Damonare的個人博客 相信每一個前端er對于跨域這兩個字都不會陌...
    秦至閱讀 1,413評論 4 51
  • 轉載:http://damonare.github.io/2016/10/30/%E5%89%8D%E7%AB%A...
    壯哉我大前端閱讀 545評論 2 9
  • 你說鳶尾寄寂,與子相惜;后來花開如海,兩生相憶。 你說引弓落月,子規哀啼;后來天地玄黃,瀟瀟暮雨。 你說煙雨畫堂,...
    木筆喬喬閱讀 528評論 0 1