【问题标题】:Firefox not firing onload for dynamic nested iframeFirefox 没有为动态嵌套 iframe 触发 onload
【发布时间】:2023-03-21 08:31:01
【问题描述】:

我有以下代码可以在 Chrome 和 MS Edge 上运行,但不能在 Firefox 上运行。

Parent.html 有这个脚本。

<html>
<body>
<script>
var ifr1 = document.createElement('iframe');

ifr1.onload = function() {
    alert("iframe 1 loaded") //fires on all browsers
    script = ifr1.contentWindow.document.createElement('script');
    script.src = 'PATH/TO/script.js';
    script.onload = function() {
        alert("script 1 onload") //fires on all browsers
    };
    ifr1.contentWindow.document.body.appendChild(script);
};
document.body.appendChild(ifr1);

</script>
</body>
</html>

它创建一个 iframe 并在该 iframe 中加载 script.js。

这里是 script.js,它与上面做同样的事情 -

var ifr2 = document.createElement('iframe');

ifr2.onload = function() {
    alert("iframe 2 loaded") //doesn't fire on Firefox
    script = ifr2.contentWindow.document.createElement('script');
    script.src = 'https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js';
    script.onload = function() {
        alert("script 2 onload")
    };
    ifr2.contentWindow.document.body.appendChild(script);
};
document.body.appendChild(ifr2);

它在 Parent.html 创建的 iframe ifr1 内创建另一个 iframe ifr2

现在,Chrome 和 Edge 可以正确显示所有警报,但 Firefox 不会触发 ifr2 的 onload 事件(在 ifr1 中加载)(即使 IE 也会触发 ifr2 的 onload)。知道为什么吗?

【问题讨论】:

  • 开发工具控制台上有任何消息吗?

标签: javascript html iframe


【解决方案1】:

一种解决方法是创建一个简单的 html 页面 - 甚至只是 &lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;(可能甚至更少).. 让我们称之为 empty.html

如果您现在将 Parent.html 更改为

<html>
<body>
<script>
var ifr1 = document.createElement('iframe');

ifr1.onload = function() {
    alert("iframe 1 loaded") //fires on all browsers
    script = ifr1.contentWindow.document.createElement('script');
    script.src = 'PATH/TO/script.js';
    script.onload = function() {
        alert("script 1 onload") //fires on all browsers
    };
    ifr1.contentWindow.document.body.appendChild(script);
};
ifr1.src = 'empty.html'; // add this code *******
document.body.appendChild(ifr1);

</script>
</body>
</html>

然后它按预期工作

不知道为什么 firefox 会这样做 - 可能是因为没有 src 属性,iframe 的位置是 about:blank - 但为什么第一个有效而不是第二个对我来说是个谜

编辑:嗯,它做了一次然后又停止了!

好的,真的很奇怪 - 如果你添加 ifr1.src = 'empty.html' 它可以工作......如果你在 script.js 中复制它,它会再次中断

不确定我是否已经很好地回答了你,但至少我给了你一个有效的工具:p

【讨论】:

    【解决方案2】:

    IMO 这是 Firefox 中的一个错误,因为 Firefox 不会按照您期望的方式在 iframe 中执行 load 事件。 Mozilla 的开发人员可能不同意。这一切都取决于您对“负载”应该意味着什么的定义,它比您想象的要复杂。

    在任何情况下,真正的问题是何时知道访问ifr2.contentWindow 是安全的,而使用ifr2.onload 的全部意义在于您可以确定ifr2.contentWindow 何时存在。

    但是请注意,在执行 document.body.appendChild(ifr2) 时会立即创建 contentWindow 和文档,因此如果将 appendChild() 调用移至当前代码上方并删除 onload 函数,它将按预期工作。

    或者,您可以将onload 函数更改为其他内容并在appendChild() 之后直接执行它,如下所示:

    var ifr2 = document.createElement('iframe');
    function loadit() {
        console.log("iframe 2 loaded")
        script = ifr2.contentWindow.document.createElement('script');
        script.src = '...';
        script.onload = function() {
            console.log("script 2 onload")
        };
        ifr2.contentWindow.document.body.appendChild(script);
    };
    
    // add the iframe to the document
    document.body.appendChild(ifr2);
    
    // now execute your script stuff:
    loadit()
    

    这应该适用于所有(现代)浏览器。

    【讨论】:

      【解决方案3】:

      虽然这是一种不好的做法,并且在 chrome 中已被弃用(它会在控制台中显示警告。 在附加脚本标记之前添加此行为我解决了这个问题:

      iframe.contentWindow.document.write('&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;');

      看来 firefox 需要它来初始化 iframe 并运行 javascript...

      【讨论】:

        猜你喜欢
        • 2014-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多