您的位置:首页 > 新闻 > 会展 > js中【postMessage】八大点解读+完整示例

js中【postMessage】八大点解读+完整示例

2025/2/28 0:29:44 来源:https://blog.csdn.net/2301_79858914/article/details/142117919  浏览:    关键词:js中【postMessage】八大点解读+完整示例

postMessage() 是 JavaScript 中一个用于在不同的窗口、iframe 或者标签页之间进行跨域通信的 API。它通过一种安全的方式允许文档之间发送消息,而不要求它们在同一个源(域名、协议、端口)上。下面详细讲解 postMessage() 相关的知识点。

1. 基本概念

postMessage() 是 HTML5 引入的 API,允许一个窗口发送消息到另一个窗口,无论它们是否同源。它广泛用于 Web 应用中,尤其是在现代网页应用程序中,用来在主页面和 iframe、弹出窗口、服务端之间进行通信。

2. 语法

window.postMessage(message, targetOrigin, [transfer]);
  • message:要发送的消息,可以是字符串或是任何可序列化的数据(例如对象、数组)。消息内容会通过结构化克隆算法进行传递,类似 JSON 序列化。
  • targetOrigin:指定可以接收消息的窗口的源(协议、域名、端口),以确保消息不会被发送到未知或不信任的站点。可以使用 "*" 表示不限制目标源,但这样可能会带来安全隐患。
  • transfer(可选):传递的对象,通常是像 ArrayBuffer 或者 MessagePort 这样的对象,这些对象会通过转移的方式而不是拷贝传递。

3. 消息接收

要接收通过 postMessage() 发送的消息,目标窗口必须监听 message 事件。可以通过以下方式注册事件处理程序:

window.addEventListener("message", function(event) {// 检查消息的来源是否可信if (event.origin !== "https://trusted-origin.com") {return;}// 处理接收到的消息console.log("Message received:", event.data);
});

4. 安全性

跨域通信中,安全性是最为重要的考虑因素。为了避免消息被不可信的站点截获或伪造,建议遵循以下安全性规则:

  • targetOrigin 的使用:总是显式指定目标源,而不是使用 "*",这样可以确保消息只会发送到特定的站点。

    window.postMessage("Hello", "https://trusted-site.com");
    
  • 验证消息来源:在接收到消息时,检查 event.origin 是否为可信的源,避免处理来自恶意站点的消息。

  • 消息的校验:在处理接收到的消息之前,确保对消息的内容进行校验,防止潜在的恶意代码注入攻击。

5. postMessage() 的应用场景

5.1. iframe 与主页面通信

postMessage() 最常见的使用场景之一是在主页面与嵌入的 iframe 之间进行通信。无论它们是否属于同一个域名,都可以通过 postMessage() 来实现安全通信。

示例:主页面发送消息给 iframe
<!-- 主页面 -->
<iframe id="myFrame" src="https://other-domain.com"></iframe>
<script>var iframe = document.getElementById('myFrame');iframe.contentWindow.postMessage('Hello iframe', 'https://other-domain.com');
</script>
示例:iframe 接收消息
<!-- iframe 页面 -->
<script>window.addEventListener('message', function(event) {if (event.origin !== 'https://trusted-domain.com') {return;}console.log('Received message from parent:', event.data);});
</script>
5.2. 跨窗口通信

在一个页面中打开了一个新窗口,可以使用 postMessage() 在父窗口和子窗口之间进行通信。

示例:父窗口发送消息给子窗口
var popup = window.open("https://other-domain.com");
popup.postMessage('Hello popup', 'https://other-domain.com');
示例:子窗口接收消息
window.addEventListener('message', function(event) {if (event.origin !== 'https://trusted-domain.com') {return;}console.log('Message from parent window:', event.data);
});
5.3. Web Workers 与主线程通信

postMessage() 也可以用于 Web Worker 和主线程之间的通信。由于 Web Worker 没有直接访问 DOM 的权限,它们需要与主线程进行通信来完成任务。

示例:主线程发送消息给 Web Worker
var worker = new Worker('worker.js');
worker.postMessage('Hello Worker');
示例:Web Worker 接收消息
// worker.js
self.addEventListener('message', function(event) {console.log('Message from main thread:', event.data);
});
5.4. Service Worker 与页面通信

Service Worker 也是一种场景,页面可以使用 postMessage() 与 Service Worker 通信,实现一些后台任务的交互。

6. event 对象的属性

当目标窗口接收到 message 事件时,event 对象会包含以下属性:

  • data:发送的消息内容。
  • origin:消息来源的协议、域名和端口。
  • source:发送消息的窗口对象,允许我们回复发送方。
  • lastEventId:消息的唯一标识符(通常在服务器发送事件中使用)。
  • ports:如果消息涉及 MessagePort 对象,则可以通过此属性获取传递的端口。

7. 注意事项

  • 跨域限制postMessage() 允许跨域发送消息,但前提是接收方必须显式监听 message 事件,否则消息不会被接收。
  • 消息序列化:消息数据在传递过程中会被序列化(结构化克隆),因此一些复杂对象(如 DOM 元素、函数)无法直接传递。
  • 性能:传递大型对象时,建议使用 transfer 参数以传递而非拷贝数据,从而提高性能。

8. 其他进阶用法

8.1. 传递 MessagePort

postMessage() 支持 MessagePort 传递,可以用于创建双向通信通道。

示例:传递 MessagePort
// 在 iframe 页面中创建一个 MessageChannel
var channel = new MessageChannel();// 将一端 port 发送给主页面
parent.postMessage('Here is a port', 'https://trusted-domain.com', [channel.port2]);// 监听消息
channel.port1.onmessage = function(event) {console.log('Received message through channel:', event.data);
};

9. 总结

postMessage() 是一个强大而灵活的 API,能够实现不同窗口、iframe、Web Worker 以及其他上下文之间的安全通信。虽然它简化了跨域通信的实现,但也带来了潜在的安全风险。使用 postMessage() 时,必须注意确保消息的发送和接收过程都是可信的,尤其是要谨慎指定 targetOrigin 和验证消息来源的 origin 属性。

10. 完整示例

以下是一个完整的跨窗口通信示例,演示了如何使用 postMessage() 在两个不同的窗口之间传递消息:

<!-- 父页面 -->
<!DOCTYPE html>
<html>
<head><title>Parent Window</title>
</head>
<body><button id="sendMessage">Send Message to Child</button><script>var popup = window.open('child.html', 'ChildWindow', 'width=400,height=400');document.getElementById('sendMessage').addEventListener('click', function() {popup.postMessage('Hello from parent', 'http://example.com');});window.addEventListener('message', function(event) {if (event.origin !== 'http://example.com') return;console.log('Received message from child:', event.data);});</script>
</body>
</html>
<!-- 子页面 (child.html) -->
<!DOCTYPE html>
<html>
<head><title>Child Window</title>
</head>
<body><script>window.addEventListener('message', function(event) {if (event.origin !== 'http://example.com') return;console.log('Received message from parent:', event.data);event.source.postMessage('Hello from child', event.origin);});</script>
</body>
</html>

这个示例展示了父窗口和子窗口如何通过 postMessage() 进行双向通信,并通过 event.origin 验证消息来源的安全性。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com