likes
comments
collection
share

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

作者站长头像
站长
· 阅读数 31

简介

跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一些跨页面通讯的方式,但是大都只是简单的罗列,并没有实际例子,所以很多小伙伴只是简单的背诵。因为没有实操,因此当面试官稍微问深一点,比如某某跨页面通讯怎么使用?有哪些坑?哪种方式最适应哪种场景?一些小伙伴们就答不上来了。

为了解决这些问题,笔者今天手把手实操,一个一个讲解常见的纯前端跨页面通讯方案,不仅会讲它们的使用还会详细说明它们的优缺点,让你们对前端跨页面通讯有更深层次的理解。

对于前端跨页面通讯,无非就是父子同页面(iframe情况)、父子异页面(window.open()打开的子页面)、兄弟页面这三种情况,下面每种跨页面通讯方式,我都会以这三种方式进行举例讲解。

postMessage

我们先来看看 postMessage

postMessageHTML5中新引入的API,它可以实现跨窗口以及跨域的通信。postMessage类似于Ajax但是它不受同源策略的限制并且通信双方都是客户端。

父子同页面

对于父子同页面的情况,postMessage是一个很好的跨页面通信方案。

我们来看看笔者demo的效果

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

可以看到,在父子同页面的情况下,postMessage是一个很好的跨页面通讯方案。

父页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>father</title>
  </head>
  <body>
    <div>
      <h3>father窗口</h3>
      <div>
        <div>
          <button onclick="send()">发送数据给子窗口</button>
        </div>
        <div id="content"></div>
      </div>
      <iframe
        id="childFrame"
        src="http://127.0.0.1:5500/js/%E8%B7%A8%E9%A1%B5%E9%9D%A2%E9%80%9A%E8%AE%AF/child.html"
        width="100%"
        height="500"
      ></iframe>
    </div>
    <script>
      // postMessage 方案
      const send = () => {
        const childPage = document.getElementById("childFrame"); // 获取iframe
        // 通过childPage.contentWindow发送数据给iframe页面
        childPage.contentWindow.postMessage(
          "<div>father发送给child的数据</div>",
          location.origin
        );
      };

      const content = document.getElementById("content");
      // 监听iframe页面发送来的数据
      window.onmessage = function (e) {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

子页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>child</title>
  </head>
  <body>
    <div>
      <h3>child窗口</h3>
      <div>
        <button onclick="send()">发送数据给父窗口</button>
      </div>
      <div id="content"></div>
    </div>
    <script>
      // postMessage 方案
      const send = () => {
        const parentPage = window.parent; // 通过window.parent获取父窗口
        parentPage.postMessage("<div>child发送给father的数据</div>", location.origin);
      };

      const content = document.getElementById("content");
      // 监听father页面发送来的数据
      window.onmessage = function (e) {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

需要注意的是:

  1. 父页面获取iframe窗口是通过iframe.contentWindow,在子页面获取父页面是通过window.parent
  2. 使用某窗口postMessage发送出来的消息,就需要在某窗口使用onmessage事件监听。

接下来我们再来看看父子异页面

父子异页面

父子异页面就是在父页面通过window.open()打开的子页面,而不是像上面一样,在父页面通过iframe内嵌子页面。这种情况又稍微复杂一点点。

我们来看看笔者demo的效果

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

兄弟1页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother1</title>
  </head>
  <body>
    <h3>brother1页面</h3>
    <div>
      <button onclick="openWindow()">打开页面</button>
      <button onclick="send()">发送数据给brother2窗口</button>
    </div>
    <div id="content"></div>
    <script>
      let childWindow = null;
      const openWindow = () => {
        childWindow = window.open( // 通过window.open的返回值获取子窗口
          "http://127.0.0.1:5500/js/%E8%B7%A8%E9%A1%B5%E9%9D%A2%E9%80%9A%E8%AE%AF/brother2.html",
          "brother2"
        );
      };

      // postMessage 方案
      const send = () => { // 子窗口对象发送消息
        childWindow.postMessage(
          "<div>brother1发送给brother2的数据</div>",
          location.origin
        );
      };

      const content = document.getElementById("content");
      window.onmessage = (e) => {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

兄弟2页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother2</title>
  </head>
  <body>
    <div>
      <h3>brother2页面</h3>
      <button onclick="send()">发送数据给brother1窗口</button>
      <div id="content"></div>
    </div>
    <script>
      // postMessage 方案
      const send = () => {
        window.opener.postMessage( // window.opener获取父窗口
          "<div>brother2发送给brother1的数据</div>",
          location.origin
        );
      };

      const content = document.getElementById("content");
      window.onmessage = (e) => {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

需要注意的是:

  1. 父页面获取子页面窗口是通过wind.open()的句柄,在子页面获取父页面是通过window.opener
  2. 使用某窗口postMessage发送出来的消息,就需要在某窗口使用onmessage事件监听。

兄弟页面

对于兄弟页面,postMessage就无能为力了。因为对于各自单独打开的页面,没法获取到窗口的句柄,也就没法进行消息的发送和监听。

优缺点分析

postMessage优点就是简单,并且在跨域场景中依然可以使用该方案。缺点是只能在父子页面的情况下才能完成通讯,并不是万能的。

BroadcastChannel

接下来我们再来看看 BroadcastChanne

BroadcastChanne接口代理了一个命名频道,可以让指定 origin 下的任意 browsing context 来订阅它。它允许同源的不同浏览器窗口,Tab 页,frame 或者 iframe 下的不同文档之间相互通信。通过触发一个 message 事件,消息可以广播到所有监听了该频道的 BroadcastChannel 对象。

说这么多官方解释可能有些懵,别急,我们看下面的例子

父子同页面

我们来看看笔者demo的效果

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

父页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>father</title>
  </head>
  <body>
    <div>
      <h3>father窗口</h3>
      <div>
        <div>
          <button onclick="send()">发送数据给子窗口</button>
        </div>
        <div id="content"></div>
      </div>
      <iframe
        id="childFrame"
        src="http://127.0.0.1:5500/js/%E8%B7%A8%E9%A1%B5%E9%9D%A2%E9%80%9A%E8%AE%AF/child.html"
        width="100%"
        height="500"
      ></iframe>
    </div>
    <script>
      // BroadcastChannel 方案
      const channel = new BroadcastChannel("test"); // 频道为test,这个频道必须相同
      const send = () => {
        channel.postMessage(
          "<div>BroadcastChannel father发送给child数据</div>"
        );
      };

      const content = document.getElementById("content");
      channel.onmessage = function (e) {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

子页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>child</title>
  </head>
  <body>
    <div>
      <h3>child窗口</h3>
      <div>
        <button onclick="send()">发送数据给父窗口</button>
      </div>
      <div id="content"></div>
    </div>
    <script>
      // BroadcastChannel 方案
      const channel = new BroadcastChannel("test"); // 频道为test,这个频道必须相同
      const send = () => {
        channel.postMessage(
          "<div>BroadcastChannel child发送给father数据</div>"
        );
      };

      const content = document.getElementById("content");
      channel.onmessage = function (e) {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

这种方式就不需要父子对象窗口的句柄了,直接使用频道通信即可。不过需要注意的是父子页面必须订阅相同的频道。

父子异页面

我们来看看笔者demo的效果。

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

父页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother1</title>
  </head>
  <body>
    <h3>brother1页面</h3>
    <div>
      <button onclick="openWindow()">打开页面</button>
      <button onclick="send()">发送数据给brother2窗口</button>
    </div>
    <div id="content"></div>
    <script>
      // BroadcastChannel 方案
      const channel = new BroadcastChannel("test");
      const send = () => {
        channel.postMessage(
          "<div>BroadcastChannel brother1发送给brother2数据</div>"
        );
      };

      const content = document.getElementById("content");
      channel.onmessage = function (e) {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

子页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother2</title>
  </head>
  <body>
    <div>
      <h3>brother2页面</h3>
      <button onclick="send()">发送数据给brother1窗口</button>
      <div id="content"></div>
    </div>
    <script>
      // BroadcastChannel 方案
      const channel = new BroadcastChannel("test");
      const send = () => {
        channel.postMessage(
          "<div>BroadcastChannel brother2发送给brother1数据</div>"
        );
      };

      const content = document.getElementById("content");
      channel.onmessage = function (e) {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

这种方式就不需要父子对象窗口的句柄了,直接使用频道通信即可。不过需要注意的是父子页面必须订阅相同的频道。

兄弟页面

兄弟页面就是两个单独打开的页面,不存在父子关系的页面,对于这种情况,BroadcastChanne也是支持的。

我们来看看笔者demo的效果

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

兄弟1页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother1</title>
  </head>
  <body>
    <h3>brother1页面</h3>
    <div>
      <button onclick="send()">发送数据给brother2窗口</button>
    </div>
    <div id="content"></div>
    <script>
      // BroadcastChannel 方案
      const channel = new BroadcastChannel("test");
      const send = () => {
        channel.postMessage(
          "<div>BroadcastChannel brother1发送给brother2数据</div>"
        );
      };

      const content = document.getElementById("content");
      channel.onmessage = function (e) {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

兄弟2页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother2</title>
  </head>
  <body>
    <div>
      <h3>brother2页面</h3>
      <button onclick="send()">发送数据给brother1窗口</button>
      <div id="content"></div>
    </div>
    <script>
      // BroadcastChannel 方案
      const channel = new BroadcastChannel("test");
      const send = () => {
        channel.postMessage(
          "<div>BroadcastChannel brother2发送给brother1数据</div>"
        );
      };

      const content = document.getElementById("content");
      channel.onmessage = function (e) {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

这种方式就不需要父子对象窗口的句柄了,直接使用频道通信即可。不过需要注意的是父子页面必须订阅相同的频道。

优缺点分析

BroadcastChannel优点是简单,不依赖窗口句柄,因此支持父子和兄弟页面通信。缺点是不支持跨域,就是通信页面必须是同源,并且兼容性稍微差点点,使用的时候需要注意。

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

storage事件

当我们往localStorage、sessionStorage里面存储数据的时候会触发storage事件。所以利用这一点我们也能实现页面间的通讯。

父子同页面

我们来看看笔者demo的效果

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

父页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>father</title>
  </head>
  <body>
    <div>
      <h3>father窗口</h3>
      <div>
        <div>
          <button onclick="send()">发送数据给子窗口</button>
        </div>
        <div id="content"></div>
      </div>
      <iframe
        id="childFrame"
        src="http://127.0.0.1:5500/js/%E8%B7%A8%E9%A1%B5%E9%9D%A2%E9%80%9A%E8%AE%AF/child.html"
        width="100%"
        height="500"
      ></iframe>
    </div>
    <script>
      // storage方案
      let i = 0;
      const send = () => {
        localStorage.setItem("fatherKey", i++); //需要注意的是要触发storage事件,每次必须存储不一样的值,或者不同的key
      };

      const content = document.getElementById("content");
      // 监听iframe页面发送来的数据
      window.addEventListener("storage", (e) => {
        console.log(e);
        content.innerHTML += "child更新了";
      });
    </script>
  </body>
</html>

子页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>child</title>
  </head>
  <body>
    <div>
      <h3>child窗口</h3>
      <div>
        <button onclick="send()">发送数据给父窗口</button>
      </div>
      <div id="content"></div>
    </div>
    <script>
      // storage方案
      let i = 0;
      const send = () => {
        localStorage.setItem("chidlKey", i++); //需要注意的是要触发storage事件,必须存储不一样的值,或者不同的key
      };

      const content = document.getElementById("content");
      // 监听iframe页面发送来的数据
      window.addEventListener("storage", (e) => {
        console.log(e);
        content.innerHTML += "father更新了";
      });
    </script>
  </body>
</html>

对于父子同页面,我们既可以使用localStorage还可以使用sessionStorage来进行存储来触发storage事件。

需要注意的是要触发storage事件,每次存储必须存储不一样的值,或者不同的key。并且storage事件不会在当前窗口触发,而是会在同源的其它窗口触发。

父子异页面

我们来看看笔者demo的效果

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

父页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother1</title>
  </head>
  <body>
    <h3>brother1页面</h3>
    <div>
      <button onclick="openWindow()">打开页面</button>
      <button onclick="send()">发送数据给brother2窗口</button>
    </div>
    <div id="content"></div>
    <script>
      // storage方案
      let i = 0;
      const send = () => {
        localStorage.setItem("brother1Key", i++); //需要注意的是要触发storage事件,每次必须存储不一样的值,或者不同的key
      };

      const content = document.getElementById("content");
      // 监听iframe页面发送来的数据
      window.addEventListener("storage", (e) => {
        console.log(e);
        content.innerHTML += "brother2发送来的数据";
      });
    </script>
  </body>
</html>

子页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother2</title>
  </head>
  <body>
    <div>
      <h3>brother2页面</h3>
      <button onclick="send()">发送数据给brother1窗口</button>
      <div id="content"></div>
    </div>
    <script>
      // storage方案
      let i = 0;
      const send = () => {
        localStorage.setItem("brother2Key", i++); //需要注意的是要触发storage事件,每次必须存储不一样的值,或者不同的key
      };

      const content = document.getElementById("content");
      // 监听iframe页面发送来的数据
      window.addEventListener("storage", (e) => {
        console.log(e);
        content.innerHTML += "brother1发送来的数据";
      });
    </script>
  </body>
</html>

对于父子异页面,我们就只能使用localStorage来进行存储来触发storage事件。

需要注意的是要触发storage事件,每次存储必须存储不一样的值,或者不同的key。并且storage事件不会在当前窗口触发,而是会在同源的其它窗口触发。

兄弟页面

我们来看看笔者demo的效果

兄弟1页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother1</title>
  </head>
  <body>
    <h3>brother1页面</h3>
    <div>
      <button onclick="send()">发送数据给brother2窗口</button>
    </div>
    <div id="content"></div>
    <script>
      // storage方案
      let i = 0;
      const send = () => {
        localStorage.setItem("brother1Key", i++); //需要注意的是要触发storage事件,每次必须存储不一样的值,或者不同的key
      };

      const content = document.getElementById("content");
      // 监听iframe页面发送来的数据
      window.addEventListener("storage", (e) => {
        console.log(e);
        content.innerHTML += "brother2发送来的数据";
      });
    </script>
  </body>
</html>

兄弟2页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother2</title>
  </head>
  <body>
    <div>
      <h3>brother2页面</h3>
      <button onclick="send()">发送数据给brother1窗口</button>
      <div id="content"></div>
    </div>
    <script>
      // storage方案
      let i = 0;
      const send = () => {
        localStorage.setItem("brother2Key", i++); //需要注意的是要触发storage事件,每次必须存储不一样的值,或者不同的key
      };

      const content = document.getElementById("content");
      // 监听iframe页面发送来的数据
      window.addEventListener("storage", (e) => {
        console.log(e);
        content.innerHTML += "brother1发送来的数据";
      });
    </script>
  </body>
</html>

对于兄弟页面,我们就只能使用localStorage来进行存储来触发storage事件。

需要注意的是要触发storage事件,每次存储必须存储不一样的值,或者不同的key。并且storage事件不会在当前窗口触发,而是会在同源的其它窗口触发。

优缺点分析

监听storage事件优点是简单、兼容性好,并且支持父子和兄弟页面通信。缺点是不支持跨域,也就是通信页面必须是同源,并且会导致本地存储存储一些无用的数据(当然你也可以在某些情况下进行清理)。

SharedWorker

SharedWorker接口代表一种特定类型的 worker,可以从几个浏览上下文中访问,例如几个窗口、iframe 或其他 worker。利用这一特性,我们也能使用它来实现跨页面通讯。

父子同页面

我们来看看笔者demo的效果

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

首先我们创建共享的 shared.js,这个js的功能相当于是一个中转站。

const ports = [];
onconnect = (e) => {
  const port = e.ports[0];
  ports.push(port);
  // 相当于是一个中转站
  port.onmessage = (evt) => {
    ports
      .filter((v) => v !== port) // 此处为了贴近其他方案的实现,剔除自己
      .forEach((p) => p.postMessage(evt.data));
  };
};

然后 创建父子页面。

父页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>father</title>
  </head>
  <body>
    <div>
      <h3>father窗口</h3>
      <div>
        <div>
          <button onclick="send()">发送数据给子窗口</button>
        </div>
        <div id="content"></div>
      </div>
      <iframe
        id="childFrame"
        src="http://127.0.0.1:5500/js/%E8%B7%A8%E9%A1%B5%E9%9D%A2%E9%80%9A%E8%AE%AF/child.html"
        width="100%"
        height="500"
      ></iframe>
    </div>
    <script>
      // SharedWorker方案
      const sharedWorker = new SharedWorker("./shared.js");
      sharedWorker.port.start();
      const send = () => {
        sharedWorker.port.postMessage("sharedWorker father发送给child的数据");
      };

      const content = document.getElementById("content");
      sharedWorker.port.onmessage = (e) => {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

子页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>child</title>
  </head>
  <body>
    <div>
      <h3>child窗口</h3>
      <div>
        <button onclick="send()">发送数据给父窗口</button>
      </div>
      <div id="content"></div>
    </div>
    <script>
      // SharedWorker方案
      const sharedWorker = new SharedWorker("./shared.js");
      sharedWorker.port.start();

      const send = () => {
        sharedWorker.port.postMessage("sharedWorker child发送给father的数据");
      };

      const content = document.getElementById("content");
      sharedWorker.port.onmessage = (e) => {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

这里需要注意的是需要一个shared.js,用来中转消息。

父子异页面

我们来看看笔者demo的效果

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

父页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother1</title>
  </head>
  <body>
    <h3>brother1页面</h3>
    <div>
      <button onclick="openWindow()">打开页面</button>
      <button onclick="send()">发送数据给brother2窗口</button>
    </div>
    <div id="content"></div>
    <script>
      // SharedWorker方案
      const sharedWorker = new SharedWorker("./shared.js");
      sharedWorker.port.start();
      const send = () => {
        sharedWorker.port.postMessage(
          "sharedWorker brother1发送给brother2数据"
        );
      };

      const content = document.getElementById("content");
      sharedWorker.port.onmessage = (e) => {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

子页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother2</title>
  </head>
  <body>
    <div>
      <h3>brother2页面</h3>
      <button onclick="send()">发送数据给brother1窗口</button>
      <div id="content"></div>
    </div>
    <script>
      // SharedWorker方案
      const sharedWorker = new SharedWorker("./shared.js");
      sharedWorker.port.start();

      const send = () => {
        sharedWorker.port.postMessage(
          "sharedWorker brother2发送给brother1数据"
        );
      };

      const content = document.getElementById("content");
      sharedWorker.port.onmessage = (e) => {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

这里需要注意的是需要一个shared.js,用来中转消息。

兄弟页面

我们来看看笔者demo的效果

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

兄弟1页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother1</title>
  </head>
  <body>
    <h3>brother1页面</h3>
    <div>
      <button onclick="send()">发送数据给brother2窗口</button>
    </div>
    <div id="content"></div>
    <script>
      // SharedWorker方案
      const sharedWorker = new SharedWorker("./shared.js");
      sharedWorker.port.start();
      const send = () => {
        sharedWorker.port.postMessage(
          "<div>sharedWorker brother1发送给brother2数据</div>"
        );
      };

      const content = document.getElementById("content");
      sharedWorker.port.onmessage = (e) => {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

兄弟2页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>brother2</title>
  </head>
  <body>
    <div>
      <h3>brother2页面</h3>
      <button onclick="send()">发送数据给brother1窗口</button>
      <div id="content"></div>
    </div>
    <script>
      // SharedWorker方案
      const sharedWorker = new SharedWorker("./shared.js");
      sharedWorker.port.start();

      const send = () => {
        sharedWorker.port.postMessage(
          "<div>sharedWorker brother2发送给brother1数据</div>"
        );
      };

      const content = document.getElementById("content");
      sharedWorker.port.onmessage = (e) => {
        console.log(e);
        content.innerHTML += e.data;
      };
    </script>
  </body>
</html>

这里需要注意的是需要一个shared.js,用来中转消息。

优缺点分析

相较于其他方案没有优势,唯一的优点是支持父子和兄弟页面通信。此外,API复杂而且调试不方便。而且通信页面也必须同源

并且兼容性也需要注意

纯前端跨页面通讯的各种姿势(父子页通讯、兄弟页通讯)跨页面通讯是前端面试常考的一个经典问题,虽然说网上有很多资料介绍了一

总结

这里笔者介绍了目前纯前端使用频率比较高的四种跨页面通信方案。他们各自都有优缺点,小伙伴们在使用的时候需要根据自身情况(特别是兼容性)选择最合适的方案。

postMessage

  1. 兼容性好,能跨源通信
  2. 不支持兄弟页面通信

BroadcastChannel

  1. 支持父子、兄弟页面通信
  2. 只能是同源页面,并且兼容性稍微逊色一点

storage

  1. 支持父子、兄弟页面通讯,兼容性好
  2. 只能是同源页面,并且会导致无效存储

SharedWorker

  1. 支持父子、兄弟页面通讯
  2. 只能是同源页面,但是使用复杂,并且兼容性也不怎么样

当然,我们还可以借助后端来进行跨页面通讯,常用的方案有websocket、Server-sent Events,因为不是纯前端方案,需要后端配合,这里笔者就不再详细介绍了。如果小伙伴们还有其它优秀的方案,欢迎评论区补充。

后记

感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!

转载自:https://juejin.cn/post/7238772205516554301
评论
请登录