用 Post Messge 实现 跨域、跨窗口 通信

367 阅读1分钟

跨域跨窗口通信有很多方案都可以解决,今天我们来说说如何使用 Post Messge

MND文档

基本使用

发送消息

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

otherWindow 是指其他窗口的一个引用 比如:

  1. iframecontentWindow属性
  2. 执行 window.open 返回的窗口对象
  3. 是命名过或数值索引的 window.frames

关键其实在于 otherWindow 或者叫做 targetWindow 更加准确,是指你要发送信息的目标页面的 window 对象,直接 window.postMessage() 调用的当前窗口的 window 对象,相当于自己给自己发,目标页当然接收不到了。 关于 targetWindow 的获取根据弹出方式不同分为两种

  1. 弹出 iframe 使用 window.top 或者 window.parent 来获取,二者的区别在于 window.parent 返回当前窗口的直接父对象,而 window.top 返回最顶层的窗口对象
  2. window.open() 打开新窗口 使用 window.opener 获取

接收消息

window.addEventListener('message', function (e) {
    console.log(e.data);
}, false)

应用场景

假设我们有这样一个需求:

A页面有一个登录按钮,点击后打开一个新窗口B(A,B页面不同源),新窗口B页面内输入账号秘密验证后,通知A窗口已经登录成功。

// A页面  
// 1. 监听 message 事件,监听事件会掉
// 2. 点击按钮,打开窗口
<body>
    <button id='login'>去登录</button>
    <script>
        let newWindow
        login.onclick=function(){
            newWindow = window.open('./b.html','Login Page','height=400,width=400,top=20,left=20')
        }
        window.addEventListener('message', function (e) {
            if(e.data==='login success'){
                console.log('登录成功')
                newWindow?.close() // 关闭新窗口
            }
        }, false)
    </script>
</body> 
 
 
 
// B页面
<body>
    <button id="loginSuccess">点击登录</button>
    <script>
        let targetWindow = window.opener; // 获取打开此页面的window对象
        
        loginSuccess.onclick=function(){
             targetWindow.postMessage('login success', '*') // 第二个参数可指定发送的目标URL,*代表所有
        }
    </script>
</body>

如果B窗口打开方式是在A页面内打开Iframe,那么 targetWindowwindow.parent 而不是 window.opener