【问题标题】:Pass value to iframe from a window从窗口将值传递给 iframe
【发布时间】:2010-10-06 21:32:32
【问题描述】:

我需要向 iframe 发送一个值。

iframe 存在于当前窗口中。我怎样才能做到这一点?

我需要在包含 iframe 的父窗口中使用 javascript。

【问题讨论】:

标签: javascript html iframe


【解决方案1】:

在你的主页中,添加这一行-

window.postMessage("Hello data from Homepage");

在你的 iframe 中,添加这一行-

window.addEventListener("message", receiveDataFromWeb);

const receiveDataFromWeb=  (data)=> {
    console.log(data);
    //this should print Hello data from Homepage
}

【讨论】:

    【解决方案2】:

    只是另一种方式。 在 iframe 中,您可以添加事件侦听器并将事件分派到父文档中:

    parent.document.addEventListener('iframe-event', (e) => {
        console.log('iframe-event', e.detail);
    });
    
    setTimeout(() => {
        console.log('dispatchEvent from iframe');
        const event = new CustomEvent('frame-ready', { detail: 'parent event dispatched from iframe' });
        parent.document.dispatchEvent(event);
    }, 1000);
    

    您可以从父级添加事件侦听器并在其自己的文档中调度事件:

    document.addEventListener('frame-ready', (e) => {
            const event = new CustomEvent('iframe-event', { detail: 'iframe event dispatched from parent' });
            document.dispatchEvent(event);
        });
    

    此外,如果在任何情况下您需要在新选项卡中打开此框架,您仍然可以使用事件进行通信。 从你的框架/标签:

    if (opener) {
            const event = new CustomEvent('frame-ready', { detail: 'parent event dispatched from new tab' });
            opener.document.dispatchEvent(event);
        }
    

    来自您的家长/开场白:

    window.open('my-frame.html', '_blank');
    
    document.addEventListener('frame-ready', (e) => {
        const event = new CustomEvent('iframe-event', { detail: 'iframe event dispatched from parent' });
        document.dispatchEvent(event);
    });
    

    请注意 window.open 会将您的 DOM 暴露给它打开的下一页,因此如果您使用它打开任何第三方 url,则必须始终使用 rel=noopener 以避免安全问题:

    window.open('third-part-url.html', '_blank', 'noopener');
    

    【讨论】:

      【解决方案3】:

      如果您在内部使用 angular 和 iframe,则需要收听 iframe 以完成加载。你可以这样做:

               document.getElementsByTagName("iframe")[0].addEventListener('load', () => {
                  document.getElementsByTagName("iframe")[0].contentWindow.postMessage(
                      {
                          call: 'sendValue',
                          value: 'data'
                      },
                      window.location.origin)
              })
      

      您将不得不以一种或另一种方式获取 iframe(有更好的方法可以在 Angular 中进行),然后等待它加载。否则,即使您在 ngAfterViewInit() 等生命周期方法中执行此操作,侦听器也不会附加到它上

      【讨论】:

        【解决方案4】:

        您要做的是将值作为参数附加到 iframe src (URL) 中。

        例如<iframe src="some_page.php?somedata=5&more=bacon"></iframe>

        然后在 some_page.php 文件中使用 php $_GET['somedata'] 从 iframe URL 中检索它。注意:iframe 在您的文件中作为单独的浏览器窗口运行。

        【讨论】:

          【解决方案5】:

          我们可以使用“postMessage”概念将数据从主窗口发送到底层 iframe。

          you can checkout more about postMessage using this link 在主窗口页面中添加以下代码

          // main window code
          window.frames['myFrame'].contentWindow.postMessage("Hello World!");
          

          我们将通过“Hello World!”向 iframe id="myFrame" 的 iframe contentWindow 发送消息。

          现在在 iframe 源代码中添加以下代码

          // iframe document code
          function receive(event) {
              console.log("Received Message : " + event.data);
          }
          window.addEventListener('message', receive);
          

          在 iframe 网页中,我们将附加一个事件侦听器来接收事件,在“接收”回调中,我们会将数据打印到控制台

          【讨论】:

            【解决方案6】:

            这是另一种解决方案,如果框架来自不同的域,则可以使用。

            var frame = /*the iframe DOM object*/;
            frame.contentWindow.postMessage({call:'sendValue', value: /*value*/}, /*frame domain url or '*'*/);
            

            在框架本身:

            window.addEventListener('message', function(event) {
                var origin = event.origin || event.originalEvent.origin; // For Chrome, the origin property is in the event.originalEvent object.
                if (origin !== /*the container's domain url*/)
                    return;
                if (typeof event.data == 'object' && event.data.call=='sendValue') {
                    // Do something with event.data.value;
                }
            }, false);
            

            但不知道哪些浏览器支持此功能。

            【讨论】:

            • 对我来说最好的答案。谢谢!
            • 很有用,虽然我相信 Chrome 的 event.originalEvent.origin 位已经过时了;我在 2019 年 12 月对 Chrome 79 的测试表明它使用了event.origin
            【解决方案7】:

            另外两个选项,它们不是最优雅的,但可能更容易理解和实现,特别是如果 iframe 需要从其父级获取的数据只是几个 var,而不是复杂的对象:

            使用 URL 片段标识符 (#)

            在容器中:

            <iframe name="frame-id" src="http://url_to_iframe#dataToFrame"></iframe>
            

            在 iFrame 中:

            <script>
            var dataFromDocument = location.hash.replace(/#/, "");
            alert(dataFromDocument); //alerts "dataToFrame"
            </script>
            

            使用 iFrame 的名称

            (我不喜欢这个解决方案 - 它滥用了 name 属性,但它是一个选项,所以我提到它是为了记录)

            在容器中:

            <iframe name="dataToFrame" src="http://url_to_iframe"></iframe>
            

            在 iFrame 中:

            <script type="text/javascript">
            alert(window.name); // alerts "dataToFrame"
            </script>
            

            【讨论】:

            • 我们不能在 iframe src URL 中使用 URL 参数吗?
            【解决方案8】:

            首先,您需要了解您有两个文档:框架和容器(包含框架)。

            从容器操作框架的主要障碍是框架异步加载。您不能简单地随时访问它,您必须知道它何时完成加载。所以你需要一个技巧。通常的解决方案是在框架中使用window.parent 来“向上”(进入包含iframe 标签的文档)。

            现在您可以调用容器文档中的任何方法。此方法可以操作框架(例如,使用您需要的参数调用框架中的一些 JavaScript in)。要知道何时调用该方法,您有两种选择:

            1. 从框架的 body.onload 调用它。

            2. 将脚本元素作为最后一件事放入调用容器方法的框架的 HTML 内容中(留给读者作为练习)。

            所以框架看起来像这样:

            <script>
            function init() { window.parent.setUpFrame(); return true; }
            function yourMethod(arg) { ... }
            </script>
            <body onload="init();">...</body>
            

            还有这样的容器:

            <script>
            function setUpFrame() { 
                var frame = window.frames['frame-id'];
                frame.yourMethod('hello');
            }
            </script>
            <body><iframe name="frame-id" src="..."></iframe></body>
            

            【讨论】:

            • @testing:当然不是。与浏览器中的其他任何内容一样,它受同源策略的约束。
            • 如果框架是通过它的id 访问的,那么我必须通过contentWindowwindow.frames['frame-id'].contentWindow MDN 中访问它
            【解决方案9】:

            取决于你的具体情况,但如果 iframe 可以在页面的其余部分加载后部署,你可以简单地使用查询字符串,a la:

            <iframe src="some_page.html?somedata=5&more=bacon"></iframe>
            

            然后在 some_page.html 的某个地方:

            <script>
            var params = location.href.split('?')[1].split('&');
            data = {};
            for (x in params)
             {
            data[params[x].split('=')[0]] = params[x].split('=')[1];
             }
            </script>
            

            【讨论】:

            • 伙伴 我要感谢您的回答 - 它解决了一个关键问题!如果您对此问题添加答案,我会将其标记为正确:stackoverflow.com/questions/2855599/…
            • 对于这个问题,这是最容易实现的答案。我推荐它。
            • 但这受到特定浏览器上 URL 最大长度的限制 :(
            • 最好的部分是:: 它适用于跨域。最适合创建可以在具有不同配置的不同站点中初始化的游戏。很棒的答案。帮了大忙。
            • 当我们的工作很简单时,这是一个很好的解决方案。无需握手通信。
            【解决方案10】:

            使用frames collection

            来自链接:

            var frames = window.frames; // or // var frames = window.parent.frames;
            for (var i = 0; i < frames.length; i++) { 
              // do something with each subframe as frames[i]
              frames[i].document.body.style.background = "red";
            }
            

            如果 iframe 有名称,您还可以执行以下操作:

            window.frames['ponies'].number_of_ponies = 7;
            

            只有当这两个页面来自同一个域时,您才能这样做。

            【讨论】:

            • 这可以从iframe到不同域的父框架完成吗?
            • 如何在 iframe 中访问number_of_ponies?我觉得我错过了一些明显的东西:/
            【解决方案11】:

            查看下面的链接,它表明可以使用 Javascript 更改页面中 iFrame 的内容,尽管您很可能会遇到一些跨浏览器问题。如果你能做到这一点,你可以使用页面中的 javascript 将隐藏的 dom 元素添加到包含你的值的 iFrame,iFrame 可以读取这些元素。 Accessing the document inside an iFrame

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2010-12-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多