# 2.iframe + postMessage 实现跨域通信

话不多话, 先把原文地址发下 使用 iframe + postMessage 实现跨域通信 (opens new window)

为什么要学习 iframe, 我们知道 PC 和 H5 都是基于 dom 的样式实现,逻辑也都是 js 代码,两端都实现一遍的话肯定做了很多重复的工作。所以为了达到样式和逻辑复用的能力,我们想了一个方法,就是通过 iframe 嵌套 H5 的页面,通过 postmessage 来做数据交互,这样就实现了用 H5 来充当预览组件,那么 PC 和 H5 的代码就只有一套了

# 1.postMessage介绍

window.postMessage MDN地址 (opens new window)

postMessage方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

语法:

otherWindow.postMessage(message, targetOrigin, [transfer]);
1
  • otherWindow:其他窗口的引用,如 iframe的contentWindow、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
  • message:将要发送到其他window的数据。
  • targetOrigin:指定那些窗口能接收到消息事件,其值可以是字符串 “*” 表示无限制,或者是一个URI。
  • transfer:是一串和message同时传递的Transferable对象,这些对象的所有权将被转移给消息的接收方,而发送方将不再保留所有权。

postMessage方法被调用时,会在所有页面脚本执行完毕之后像目标窗口派发一个 MessageEvent 消息,该MessageEvent消息有四个属性需要注意:

  • type:表示该message的类型
  • data:为 postMessage 的第一个参数
  • origin:表示调用postMessage方法窗口的源
  • source:记录调用postMessage方法的窗口对象

# 2.搭建2个页面

# 3.效果截图

# 我用Node服务器搭建了一个本地服务器, 展示父子通信的效果


xcooo

# 4.代码截图


xcooo

# 5.代码

# a.html


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>iframe+postMessage 跨域通信 主页面</title>
  </head>
  <body>
    <h1>主页面</h1>
    <iframe id="child" src="http://localhost:3000/b.html"></iframe>
    <div>
      <h2>主页面接收消息区域</h2>
      <span id="message"></span>
    </div>

    <script>
      // 父向子发送消息
      window.onload = function () {
        document
          .getElementById("child")
          .contentWindow.postMessage(
            "主页面消息",
            "http://localhost:3000/b.html"
          );
      };
      // 父接收子发送的消息
      window.addEventListener(
        "message",
        function (event) {
          document.getElementById("message").innerHTML =
            "收到" + event.origin + "消息:" + event.data;
        },
        false
      );
    </script>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# b.html


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>iframe+postMessage跨域通信 子页面</title>
  </head>
  <body>
    <h2>子页面</h2>
    <div>
      <h3>接收消息区域</h3>
      <span id="message"></span>
    </div>

    <script>
      // 子接收父发送的消息
      window.addEventListener('message',function(event){
          if(window.parent !== event.source){return}
          console.log(event);
          document.getElementById('message').innerHTML = "收到" 
              + event.origin + "消息:" + event.data;
          // 子向父发送消息
          top.postMessage("子页面消息收到", 'http://localhost:3000/a.html')
      }, false);
  </script>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
上次更新: 2020/10/23 下午7:23:27