MDN中这样描述其参数targetOrigin:通过窗口的 origin 属性来指定哪些窗口能接收到消息事件,其值可以是字符串*,表示无限制,也可以是一个URI。我尝试了一下,targetOrigin不生效
我是通过VSCode编写的代码,通过其Live Server插件启动一个本地服务。代码如下
// main.html
<body>
<h1>Main Window</h1>
<button id="postMessage">post message</button>
<iframe src="content.html" id="content_iframe" width="400" height="200"></iframe>
<script>
const contentIframe = document.getElementById('content_iframe');
const button = document.getElementById('postMessage');
button.addEventListener('click', () => {
// A
window.postMessage({ type: 'main', data: 'from main' });
});
window.addEventListener('message', e => {
const { data: { type, data } } = e;
console.log(`main window received a message. message=${type}, data=${data}`);
});
</script>
</body>
// content.html
<body>
<h1>Content Window</h1>
<button id="postMessage">post message</button>
<script>
const button = document.getElementById('postMessage');
button.addEventListener('click', () => {
// B
window.postMessage({ type: 'content', data: 'from content' });
});
window.addEventListener('message', e => {
const { data: { type, data } } = e;
console.log(`content window received a message. message=${type}, data=${data}`);
});
</script>
</body>
尝试测试以下场景:
- A处采用window.postMessage,不指定targetOrigin,只有main.html收到消息;
- A处采用window.postMessage,指定targetOrigin为*,只有main.html收到消息;
- A处采用contentIframe.contentWindow.postMessage,不指定targetOrigin,只有content.html收到消息;
- A处采用contentIframe.contentWindow.postMessage,指定targetOrigin为*,只有content.html收到消息;
- B处采用window.postMessage,不指定targetOrigin,只有content.html收到消息;
- B处采用window.postMessage,指定targetOrigin为*,只有content.html收到消息;
- B处采用parent.potMessage,不指定targetOrigin,只有main.html收到消息;
- B处采用parent.potMessage,指定targetOrigin为*,只有main.html收到消息;
经过以上测试,我总结为:通过window.postMessage实现两个窗口的通信,不管是否跨源,想要给对方发消息就必须要持有对方的引用,但我想不明白如何去总结targetOrigin,它貌似没什么作用
可以看看它的英文描述:
指定接收消息的window的origin以便接收事件。
应该是这么理解,targetOrigin 是为了确保真的发送过去消息的时候,发对了“人”。假设你的content_iframe突然跳到其他页面C去了,然后你的main.html还往它发消息的时候,targetOrigin保证了其他页面C不会接收到这个事件。为了安全~