天天看點

iframe嵌入頁面跨域通信

在項目中可能會通過iframe直接将另一個頁面嵌入進來,某些場景下還可能會進行一些消息的傳遞通信。之前做過一次,就是我們開發的主系統,然後下面還有很多子系統,子系統都是通過iframe嵌入進來的,然後為了實作某些需求,需要将token傳遞給子系統,拱子系統使用,但是當時一直忙着開發,忘記記錄了,是以這篇算是補上吧

嵌入進來的頁面的window跟我們現在的window已經不是同一個了,更不是同一個document。

然後跨域通信的話,父視窗向子視窗我們通過 iframe.contentWindow.postMessage 發送消息;子視窗向父視窗我們通過 window.parent.postMessage 發送消息;然後接受的話都是監聽window的message事件,如下:

otherWindow.postMessage(message, targetOrigin, [transfer]);      
  • message

         是我們發送的資訊,一般我會傳個JSON,也可以是個對象、字元串。。

  • targetOrigin

父視窗向子視窗發送消息

iframe.contentWindow.postMessage(JSON.stringify({
  type: 'www',
  ctx: '給你消息,收到了嘛?'
}), '*')      

子視窗向父視窗發送消息 

window.parent.postMessage(JSON.stringify({
  type: 'yes',
  ctx: '我收到您發送的消息了!'
}), '*')      

接受消息 

// 接受消息
window.addEventListener('message', receiveMessage, false)

function receiveMessage(event) {
  const msg = JSON.parse(event.data)
  console.log(msg, '----->>>')
}      

測試的完整代碼 

父視窗

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <style>
    * {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }
    .content {
      width: 100vw;
      height: 100vh;
      position: relative;
    }
    .content button {
      position: absolute;
      top: 150px;
      left: 50%;
      transform: translateX(-50%);
    }
    .iframe {
      width: 500px;
      height: 500px;
      border: 1px solid #ccc;
      border-radius: 6px;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
  </style>

  <div class="content">
    <button id="btn">SEND</button>
    <div class="iframe">
      <iframe id="my-iframe" src="./iframe.html" style="width: 100%;height: 100%;" frameborder="0"></iframe>
    </div>
  </div>

  <script>
    const $ = name => document.querySelector(name)
    
    // 發送消息到子視窗
    $('#btn').onclick = function(e) {
      $('#my-iframe').contentWindow.postMessage(JSON.stringify({
        type: 'www',
        ctx: '給你消息,收到了嘛?'
      }), '*')
    }

    // 接受子視窗的消息
    window.addEventListener('message', receiveMessage, false)

    function receiveMessage(event) {
      const msg = JSON.parse(event.data)
      console.log(msg, '----->>>')
    }
  </script>
</body>
</html>      

子視窗 (iframe.html)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <style>
    * {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }
    .iframe-content {
      width: 100vw;
      height: 100vh;
      background-color: #f5f5f5;
      text-align: center;
      line-height: 100vh;
    }
  </style>

  <div class="iframe-content">
    <span>我是Iframe</span>
    <button id="iframe-btn">SEND</button>
  </div>
  <script>

    // 接受父視窗的消息
    window.addEventListener('message', receiveMessage, false)

    function receiveMessage(event) {
      const msg = JSON.parse(event.data)
      console.log(msg, '----->>>')
    }

    // 10s後發送消息到父視窗
    setTimeout(() => {
      window.parent.postMessage(JSON.stringify({
        type: 'yes',
        ctx: '我收到您發送的消息了!'
      }), '*')
    }, 5000)
  </script>
</body>
</html>      

繼續閱讀