跨域iframe数据收发异常:Angular与React间postMessage失效排查
跨域iframe postMessage通信失败问题
我在运行于http://localhost:4200的Angular应用中嵌入了一个HTML-CSS-JS编辑器,编辑器的body内包含指向http://localhost:3000(React应用)的iframe。需要向该React应用传递字符串值并接收,两者属于不同域名、不同浏览器窗口。尝试用iframe的postMessage但未成功。
我的尝试
Angular应用侧(HTML-CSS-JS编辑器中)
HTML:
<iframe src="http://localhost:3000/test"></iframe>
JS:
window.parent.postMessage('stringValue', 'http://localhost:3000/test');
React应用侧(Test.jsx)
useEffect(() => { const handleMessage = (event) => { console.log('Received message. Origin:', event.origin, 'Data:', event.data); // Check the origin of the data if (event.origin !== 'http://localhost:4200') { return; } // Handle the message console.log('Handling message:', event.data); }; window.addEventListener('message', handleMessage); return () => { // Cleanup: Remove the event listener when the component is unmounted window.removeEventListener('message', handleMessage); }; }, []);
当前控制台输出
React应用控制台收到非目标消息:
{ "type": "webpackWarnings", "data": [ "WARNING in ./src/pages/projectDetails.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!./node_modules/source-map-loader/dist/cjs.js!./src/pages/projectDetails.css)\nModule Warning (from ./node_modules/postcss-loader/dist/cjs.js):\nWarning\n\n(129:5) autoprefixer: end value has mixed support, consider using flex-end instead", "WARNING in ./src/pages/main.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!./node_modules/source-map-loader/dist/cjs.js!./src/pages/main.css)\nModule Warning (from ./node_modules/postcss-loader/dist/cjs.js):\nWarning\n\n(1286:3) autoprefixer: end value has mixed support, consider using flex-end instead", "WARNING in ./src/pages/main.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!./node_modules/source-map-loader/dist/cjs.js!./src/pages/main.css)\nModule Warning (from ./node_modules/postcss-loader/dist/cjs.js):\nWarning\n\n(1287:3) autoprefixer: end value has mixed support, consider using flex-end instead", "WARNING in ./src/pages/main.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!./node_modules/source-map-loader/dist/cjs.js!./src/pages/main.css)\nModule Warning (from ./node_modules/postcss-loader/dist/cjs.js):\nWarning\n\n(1318:3) autoprefixer: start value has mixed support, consider using flex-start instead", "WARNING in ./src/pages/main.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!./node_modules/source-map-loader/dist/cjs.js!./src/pages/main.css)\nModule Warning (from ./node_modules/postcss-loader/dist/cjs.js):\nWarning\n\n(1350:3) autoprefixer: start value has mixed support, consider using flex-start instead", "WARNING in ./src/pages/main.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!./node_modules/source-map-loader/dist/cjs.js!./src/pages/main.css)\nModule Warning (from ./node_modules/postcss-loader/dist/cjs.js):\nWarning\n\n(1351:3) autoprefixer: start value has mixed support, consider using flex-start instead", "WARNING in ./src/pages/main.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!./node_modules/source-map-loader/dist/cjs.js!./src/pages/main.css)\nModule Warning (from ./node_modules/postcss-loader/dist/cjs.js):\nWarning\n\n(1543:3) autoprefixer: end value has mixed support, consider using flex-end instead", "WARNING in ./src/pages/main.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!./node_modules/source-map-loader/dist/cjs.js!./src/pages/main.css)\nModule Warning (from ./node_modules/postcss-loader/dist/cjs.js):\nWarning\n\n(1544:3) autoprefixer: end value has mixed support, consider using flex-end instead" ] }
期望结果
React应用中收到event.origin为http://localhost:4200,并在event.data中获取到iframe发送的字符串数据。
问题分析与修正方案
核心问题
- 发送方向错误:你用
window.parent.postMessage是向父窗口(Angular应用)发送消息,而非向iframe内部的React应用发送。正确方式是调用iframe元素的contentWindow.postMessage。 - 目标Origin格式错误:
postMessage的第二个参数应为目标应用的origin(http://localhost:3000),不能包含路径。 - 未等待iframe加载完成:直接发送消息可能在React应用未加载时触发,导致消息丢失。
修正后的代码
Angular应用侧
给iframe添加ID,监听加载完成后再发送消息:
HTML:
<iframe id="reactIframe" src="http://localhost:3000/test"></iframe>
JS:
const iframe = document.getElementById('reactIframe'); iframe.addEventListener('load', () => { // 向React应用发送消息,指定正确的origin iframe.contentWindow.postMessage('stringValue', 'http://localhost:3000'); });
React应用侧
优化监听逻辑,过滤非目标消息:
import { useEffect } from 'react'; function Test() { useEffect(() => { const handleMessage = (event) => { // 严格校验来源,忽略无关消息(如webpack警告) if (event.origin !== 'http://localhost:4200') return; console.log('收到来自Angular的消息:', event.data); }; window.addEventListener('message', handleMessage); return () => { window.removeEventListener('message', handleMessage); }; }, []); return <div>Test Page</div>; } export default Test;
额外注意事项
- 严格校验消息来源是跨域通信的安全必备,避免恶意消息注入。
- 如果使用的是第三方HTML编辑器,需确保编辑器允许访问父窗口DOM,或调整消息发送的上下文(比如在编辑器的代码运行环境中直接向iframe发送)。
内容的提问来源于stack exchange,提问作者Jainy James
相关产品推荐
相关产品推荐

