浏览器中不同页面之前的通信

1,681 阅读4分钟

业务场景

在我们开发多页面应用的时候,可能会遇到多个页面之间通信的需求。这个时候可能会涉及到两个场景:

  1. 这些多页面显示在不同的浏览器标签页中
  2. 在一个页面中使用iframe标签引用的多个页面,在这些页面之间进行通信

明确场景之后,我们还需要知道另外一个条件,即是否这些页面之间是否跨域。多页面之间是否跨域直接决定我们能不能使用某些方法来解决通信问题,下面我们进行详细介绍。

多页面之间不涉及跨域

如果多个页面之间不涉及跨域,那么我们可以采用以下四种方式进行页面之间通信:

1. cookie

比如在页面A中,我们设置一个cookie如下:

document.cookie = "userName=Allen";

这个时候我们在页面B中通过cookie就可以读取到设置的username的值:

console.log(document.cookie);    // userName=Allen
2. localStorage

和cookie类似,我们可以通过localStorage来实现多页面之间的通信,而且使用localStorage的时候,我们还可以通过事件绑定来实时捕捉到localStorage的变化,方便我们进行逻辑处理。

比如在A页面,我们首先进行绑定storage事件,获取相关的数据:

window.addEventListener("storage", function (e) {
    console.log(e);
});

然后在B页面,通过以下代码保存数据到localStorage:

setTimeout(function () {
    localStorage.setItem("name2", "Allen");
}, 3000);

三秒钟后到A页面的控制台中,我们就可以看到到引出来的storage事件信息。

3. postMessage

该方法同时适用于跨域的场景,具体介绍请参考后文。

4. webScoket

该方法同时适用于跨域的场景,具体介绍请参考后文。

多页面之间涉及跨域

如果多页面之间设计跨域,那么我们可以采用以下两种方式来实现页面之间的通信:

1. postMessage

window.postMessage()方法安全地启用Window对象之间的跨域通信。要注意的是,如果我们想使用这种方法在两个页面之间进行通信,必须要获取到两个页面的window对象。下面给出来两个实例:

实例1: 在页面A中通过iframe标签引用B页面,在这两个页面之间进行通信

页面A的代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Page A</title>
        <script>
            window.onload = function () {
                let data = {
                    name: "Allen",
                    height: 175
                }

                // 给B页面发送消息,此时A页面是发送者
                setTimeout(function () {
                    // 注意:这里要获取到页面B的window对象
                    // 然后使用这个对象的postMessage方法,来触发页面B的message事件
                    window.frames[0].postMessage(data, "*");
                }, 3000);

                // 接受B页面发来的消息,此时A页面是接受者
                window.addEventListener("message", function (e) {
                    console.log(e);
                });
            }
        </script>
    </head>

    <body>
        我是A页面
        <iframe src="./B.html" frameborder="0"></iframe>
    </body>
</html>

页面B的代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Page B</title>
        <script>
            window.onload = function () {
                // 接受A页面发来的消息,此时B页面是接受者
                window.addEventListener("message", function (e) {
                    console.log(e);
                    returnMessage();
                });
            }

            // 给A页面发送消息,此时B页面是发送者
            function returnMessage() {
                let data = "Hi A, 你发给我的消息我已经接收到了";
                window.parent.postMessage(data, "*");
            }
        </script>
    </head>
    <body>
        我是B页面
    </body>
</html>

实例2: 在A页面中通过window.open()方法打开B,在这两个页面之间进行通信

页面A的代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Page A</title>
        <script>
            window.onload = function () {
                let data = {
                    name: "Allen",
                    height: 175
                }

                // 这里要获取到页面B的window对象
                let pageBWin = window.open("./B.html", "child");

                // 给B页面发送消息,此时A页面是发送者
                setTimeout(function () {
                    pageBWin.postMessage(data, "*");
                }, 3000);
            }
        </script>
    </head>
    <body>
        我是A页面
    </body>
</html>

页面B的代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Page B</title>
        <script>
            window.onload = function () {
                // 接受A页面发来的消息,此时B页面是接受者
                window.addEventListener("message", function (e) {
                    console.log(e);
                });
            }
        </script>
    </head>
    <body>
        我是B页面
    </body>
</html>

这时如果想从B页面向A页面发送消息,可以通过window.opener获取到A页面的window对象,然后通过该对象的postMessage()方法进行通信。

2. webScoket方法

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。涉及的内容较多,这里推荐大家阅读阮一峰老师的教程进行学习:WebSocket 教程

写在最后

以上便是这篇博客的全部内容,如果错误之后,还希望各位打来及时指正!