工作中遇到iframe 和父级页面交互问题,及在iframe内部关闭父级页面,我用到的方法是跨域通信window.postMessage。window.postMessage 是一种安全且高效的方法,允许不同源的窗口之间进行通信。本文将详细介绍如何使用 window.postMessage 实现从 iframe 关闭父页面的弹框功能。
一、window.postMessage 介绍
window.postMessage 是一种浏览器提供的安全通信机制,允许不同源的窗口之间传递消息。它通过以下两个步骤实现通信:
- 发送消息:使用
window.postMessage方法向目标窗口发送消息。 - 接收消息:通过监听
message事件接收消息,并根据消息内容执行相应操作。
二、解决方法
(一)发送消息
在 iframe 页面中,使用 window.parent.postMessage 向父页面发送消息。postMessage 方法接受两个参数:
- message:要发送的消息内容,可以是字符串、对象等。
- targetOrigin:目标窗口的源,用于指定消息可以发送到哪些源。为了安全起见,应尽可能指定一个具体的源,而不是使用通配符
*。
window.parent.postMessage('close-modal', 'http://origin.com');
(二)接收消息
在父页面中,监听 message 事件以接收来自 iframe 的消息。通过 event 对象可以获取消息内容和发送消息的窗口的源。为了安全起见,应验证 event.origin 是否为预期的源。
// 在父页面中
window.addEventListener('message', function(event) {
// 验证消息的来源
if (event.origin !== 'http://iframe-source-domain.com') {
console.warn('Invalid message origin:', event.origin);
return;
}
// 处理接收到的消息
if (event.data === 'close-modal') {
closeModal();
}
});
closeModal() {
// 关闭弹框
document.getElementById('modal').style.display = 'none';
}
三、完整示例
(1)父页面代码
<body>
<div id="app">
<button onclick="openModal()">Open</button>
<div id="modal" class="ant-modal-root" style="display: none;">
<div class="ant-modal-mask"></div>
<div class="ant-modal-wrap">
<div class="ant-modal">
<div class="ant-modal-content">
<div class="ant-modal-body">
<iframe src="./iframe.html" style="width: 100%; height: 300px;"></iframe>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function openModal() {
document.getElementById('modal').style.display = 'block';
}
function closeModal() {
document.getElementById('modal').style.display = 'none';
}
// 监听来自 iframe 的消息
window.addEventListener('message', function (event) {
// 验证消息来源(这里假设父子页面同源,使用 '*' 作为示例)
if (event.origin !== 'http://localhost') {
console.warn('Invalid message origin:', event.origin);
return;
}
if (event.data === 'close-modal') {
closeModal();
}
});
</script>
</body>
(2)iframe 页面代码
<body>
<button onclick="closeParentModal()">Close</button>
<script>
function closeParentModal() {
// 向父页面发送关闭弹框的消息
window.parent.postMessage('close-modal', '*');
}
</script>
</body>
四、注:
- 验证
event.origin:为了防止恶意网站发送消息,务必验证event.origin是否为预期的源。 - 使用具体源:在调用
postMessage时,尽量使用具体的源而不是通配符*,以提高安全性。 - 处理消息内容:对接收到的消息内容进行验证和处理,确保其符合预期格式和内容。
window.parent.postMessage可以发送复杂数据:比如对象或数组。该方法支持 JSON 可序列化的数据,因此您可以将 JavaScript 对象和数组作为消息内容传递。只需确保数据可以在 iframe 和父窗口之间安全地序列化和反序列化。