乐闻世界logo
搜索文章和话题

How to communicate between iframe and the parent site

9 个月前提问
5 个月前修改
浏览次数79

6个答案

1
2
3
4
5
6

当iframe页面需要和其父站点进行通信时,主要依靖于JavaScript中的几种机制来实现。下面我将详细介绍几种常见的通信方式及其应用场景:

1. 使用postMessage方法

postMessage是HTML5中引入的一种安全的跨源通信方法。它允许来自不同源的页面进行数据交换,避免了直接通过DOM进行交互可能引起的安全问题。

父页面向iframe发送消息的例子:

javascript
// 在父页面中 var iframe = document.getElementById('myIframe'); iframe.contentWindow.postMessage('Hello iframe!', 'http://iframe-domain.com');

iframe接收消息的例子:

javascript
// 在iframe中 window.addEventListener('message', function(event) { if (event.origin !== 'http://parent-domain.com') { // 可以通过检查event.origin来验证发消息方的源 return; } console.log('Received message from parent:', event.data); });

2. 直接操作DOM元素

如果iframe页面与父页面同源,也就是说它们的协议、域名和端口都相同,那么它们之间可以直接通过JavaScript操作对方的DOM。

父页面访问iframe DOM的例子:

javascript
// 在父页面中 var iframeDocument = document.getElementById('myIframe').contentDocument; var elementInIframe = iframeDocument.getElementById('someElement'); elementInIframe.innerHTML = 'Hello from parent page!';

iframe访问父页面DOM的例子:

javascript
// 在iframe中 var parentDocument = window.parent.document; var elementInParent = parentDocument.getElementById('someElementInParent'); elementInParent.innerHTML = 'Hello from iframe!';

3. 使用JavaScript回调函数

在某些情况下,父页面可以将函数作为全局变量或者作为iframe窗口的属性传入,这样iframe就可以直接调用这些函数来与父页面通信。

父页面提供一个可被iframe调用的函数的例子:

javascript
// 在父页面中 function parentFunction(message) { console.log('Message from iframe:', message); }

iframe调用父页面函数的例子:

javascript
// 在iframe中 window.parent.parentFunction('Hi, parent!');

注意事项和安全考虑:

  1. 跨域通信时务必使用postMessage,并且验证消息来源event.origin确保安全。
  2. 通过DOM直接操作时要注意跨域问题,只有同源时才能执行。
  3. 在使用全局函数进行通信时,要注意可能导致的命名冲突和函数作用域的问题。

通过上述机制,iframe页面和父站点可以有效地进行通信,同时保持安全性和灵活性。在实现这些通信机制时,我们必须考虑到安全性问题,确保不会暴露敏感信息或者允许潜在的恶意行为。

2024年6月29日 12:07 回复

对于不同的域,无法直接调用方法或访问 iframe 的内容文档。

您必须使用跨文档消息传递

父级 -> iframe

例如在顶部窗口中:

shell
myIframe.contentWindow.postMessage('hello', '*');

并在 iframe 中:

shell
window.onmessage = function(e) { if (e.data == 'hello') { alert('It works!'); } };

iframe -> 父级

例如在顶部窗口中:

shell
window.onmessage = function(e) { if (e.data == 'hello') { alert('It works!'); } };

并在 iframe 中:

shell
window.top.postMessage('hello', '*')
2024年6月29日 12:07 回复

在 2018 年和现代浏览器中,您可以将自定义事件从 iframe 发送到父窗口。

内嵌框架:

shell
var data = { foo: 'bar' } var event = new CustomEvent('myCustomEvent', { detail: data }) window.parent.document.dispatchEvent(event)

家长:

shell
window.document.addEventListener('myCustomEvent', handleEvent, false) function handleEvent(e) { console.log(e.detail) // outputs: {foo: 'bar'} }

PS:当然,你也可以用同样的方式向相反方向发送事件。

shell
document.querySelector('#iframe_id').contentDocument.dispatchEvent(event)
2024年6月29日 12:07 回复

用于event.source.window.postMessage发送回发件人。

来自内嵌框架

shell
window.top.postMessage('I am Iframe', '*') window.onmessage = (event) => { if (event.data === 'GOT_YOU_IFRAME') { console.log('Parent received successfully.') } }

然后从父母那里说回来。

shell
window.onmessage = (event) => { event.source.window.postMessage('GOT_YOU_IFRAME', '*') }

更新:

postMessage不应该在跨域上工作,所以解决方案如下:

例如您的网站是:customer.com您的域名是my.com

你需要这样做

  • 创建一个js文件(上传到CDN或您的服务器)-my.com
  • 将上面的js文件嵌入到customer.com

现在my.com,您可以postMessage从上面的嵌入脚本接收来自您的数据。

2024年6月29日 12:07 回复

在花了 2 天尝试让 iFrame 将消息发送回父级(在我的情况下是一个 Vue 应用程序)后,我发现了这个出色的参考:

https://dev-bay.com/iframe-and-parent-window-postmessage-communication/

从 iframe 到父级:

shell
const parentWindow = window.parent; class Message { constructor(type, body) { this.type = type; this.body = body; } }; function sendMessage (windowObj, payload) { if(windowObj) { windowObj.postMessage(payload, "*"); } }; //Then call appropriately: sendMessage(parentWindow, new Message("button-click", "Show Stats Overlay"));

在父级中,我的 Vue 应用程序安装了生命周期事件,但请参考您自己的要求的链接:

shell
window.addEventListener("message", (e) => { var data = e.data; console.log("RECEIVED message from CHILD TO PARENT", data); var type = data.type; var body = data.body; if(type === "button-click" && body) { console.log("button-click RECEIVED FROM CHILD") //Additional functionality ... } else if (type === "text-msg" && body) { console.log("TEXT MESSAGE RECEIVED FROM CHILD"); //Additional functionality ... } });

请参阅参考资料以了解从 Parent 到 iFrame 的通信示例。

希望这对其他人有帮助。

2024年6月29日 12:07 回复

你的答案