子页面通过postMessage向父页面回传消息时,父页面接收内容始终为空的技术咨询
解决跨窗口postMessage回传内容为空的问题
首先,咱们先拆解你的问题:父窗口发消息给子窗口正常,但子窗口回传时,父窗口的监听触发了,但你觉得接收的内容为空。结合你的代码,我发现几个可以优化的点,以及可能导致你看到“内容为空”的原因:
1. 先确认你看到的“空”是不是控制台的显示错觉
你在父页面里写了:
function message_receive(evt) { console.log('event', evt); console.log(evt); }
有些浏览器的控制台在打印对象时,如果对象是引用类型,后续展开时可能会显示成空(因为对象被垃圾回收或者内部状态变化),但实际evt.data才是你要接收的消息内容。建议你修改成直接打印evt.data,这才是关键:
function message_receive(evt) { console.log('Received event origin:', evt.origin); console.log('Received message content:', evt.data); // 重点看这个! }
2. 子页面不要依赖父消息来获取父窗口引用,直接用window.opener
你的子页面里通过监听父消息来存储this.parentWindow,但父页面每隔5秒就发一次消息,会反复覆盖这个变量——虽然这不会直接导致消息为空,但这种方式不够可靠。其实window.open打开的子窗口自带window.opener属性,直接指向父窗口,用这个更简单稳定:
修改子页面(Angular)代码:
ngOnInit() { // 监听父消息时,一定要精确验证来源origin,避免恶意消息 window.addEventListener('message', (event) => { // 替换成父页面的实际origin(比如http://www.tablesandlegs.co.uk:8080) if (event.origin !== 'http://www.tablesandlegs.co.uk:8080') { return; } console.log('From parent:', event.data); }); } public clicked() { // 先检查父窗口是否还存在(没被关闭) if (window.opener && !window.opener.closed) { // 明确指定父窗口的origin,不要用*(安全最佳实践) window.opener.postMessage('you clicked something', 'http://www.tablesandlegs.co.uk:8080'); } else { console.log('Parent window is closed or unavailable'); } }
3. 父页面也要验证消息来源的origin
这是安全层面的必要操作,避免接收来自未知网站的恶意消息:
function message_receive(evt) { // 替换成子页面的实际origin(比如http://www.new.tablesandlegs.co.uk:8085) if (evt.origin !== 'http://www.new.tablesandlegs.co.uk:8085') { return; } console.log('Received from child:', evt.data); }
关于iframe的疑问:完全不需要!
你提到的iframe是嵌入页面的通信场景,而你的场景是独立窗口之间的通信,用window.open + postMessage完全可以实现双向通信,根本不需要改用iframe。那些教程提到iframe只是另一种通信场景的解决方案,和你的情况无关。
为什么之前的代码可能出现“内容为空”?
- 大概率是浏览器控制台的显示问题:单独打印
evt对象时,控制台的延迟展开可能让你误以为它是空,但实际evt.data是有内容的,直接打印evt.data就能看到真实消息。 - 子页面的
this.parentWindow可能在父多次发消息时被覆盖,但这不会导致消息为空,只是不够可靠,换成window.opener就解决了。
内容的提问来源于stack exchange,提问作者Oam Psy
相关产品推荐
相关产品推荐

