JsWeb前端之路让前端飞

Javascript 基础夯实—— postMessage

2017-09-03  本文已影响77人  ac68882199a1

平时工作中可能会碰到类似的需求:在当前页面打开一个新的窗口,当这个新窗口的页面中的数据发生变化时,需要对上一个窗口的页面状态进行一些调整

上面的这个需求与事件监听非常类似,都是触发了某个事件时执行某个动作。但是一般这种监听(或者订阅、广播)都只能在同一个页面中,并不能够跨窗口

那么不通过监听,该如何实现两个窗口之间的通信呢?其实 html5 已经有现成的方法来实现了

postMessage 方法

在 html5,window 对象上有一个方法叫做postMessage,与它的名字一样,这个方法就是用来发送信息的,但是它只能用来在两个窗口之间发送信息

老套路,先来看看这个方法的参数和使用

win.postMessage(data, origin)

// win 这个参数为需要接受消息的 window 对象
// 当我们通过 window.open() 打开一个新窗口时,会返回一个新窗口的 window 对象,通过这个新窗口的 window 对象,就可以向新窗口发送消息
// 如果页面中有 frame 时,也可以通过这个 frame 对象发送消息

// data 为我们想要发送的数据,理论上 data 可以是任何可以被复制的数据类型,但是由于部分浏览器只支持传输 String 类型,所以传输的数据最好是通过 JSON.stringify() 序列化后再传输

// origin 为字符串,为目标窗口的源,由 协议+ip/域名+端口号 组成
// 如果想要传递给任意窗口,可以将这个参数设置为 * ,为了安全起见,不建议设置为 *
// 如果目标窗口与当前窗口同源,则设置为 /

知道了如何使用postMessage方法,那么又该如何实现数据的接收呢?并不难

window.addEventListener('message', function (e) {...})

// 第一个参数为这个事件监听器的类型,'message' 表示会监听当前窗口接收到的消息
// 第二个参数为接收到消息后的回调函数,在回调函数中,我们可以对发送消息的源进行一些验证,从而保证安全性
// 回调函数参数 e 上有很多属性,我们可以将其打印出来,其中 origin 表示发送消息窗口的源;source 属性表示发送消息的窗口,通过 e.source == window.opener 可以判断发送消息的窗口与打开当前页面的窗口是否为同一个;data 属性标书传递过来的数据

消息的发送与接收并不难,那么下面就来实现一下文章开篇时候提出来的需求

superWindow.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>super window</title>
</head>
<body>

<h3>super window</h3>
<p id="message"></p>

<a href="javascript:;" id="post">打开新窗口并监听消息</a>

<script>

    document.getElementById('post').onclick = function () {
        // 打开一个新窗口
        var subWindow = window.open('subWindow.html')
        // 监听 message 事件
        window.addEventListener('message', function (e) {
            console.log(e)
            // 校验发送消息的窗口的源
            if (e.origin != 'http://192.168.1.101:8081') return
            document.getElementById('message').innerText = e.data
        } )
    }

</script>
</body>
</html>

subWindow.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>sub window</title>
</head>
<body>

<h3>sub window</h3>

<script>

    // 通过 window.opener 获取到打开当前窗口的窗口,即 super window
    // 由于当前是同源窗口传递消息,所以第二个参数设为 /
    window.opener.postMessage('super window 接收到了一条消息', '/')
    
</script>
</body>
</html>

通过 superWindow 打开了 subWindow,subWindow 在打开后向 superWindow 发送了一条消息,superWindow 在接收到后进行了校验并处理

下面是效果截图

  1. super window 的初始状态
  1. 点击按钮打开 sub window
  1. 返回 super window 查看页面状态

当然,上面这个例子很简单,感兴趣的小伙伴还可以通过这个方法实现类似两个指定窗口之间的对话功能等等

跨域

postMessage 还有一个很重要的特性就是跨域,将第二个参数设置为其他的源,就可以实现两个不同域网站的通信(前提是该域做了接受消息的处理)

这个特性小伙伴可以自己试试,只需将上面的例子稍加改动就可以了

扫码关注前端周记公众号
上一篇下一篇

猜你喜欢

热点阅读