为啥 iframe.contentWindow == null?

Posted

技术标签:

【中文标题】为啥 iframe.contentWindow == null?【英文标题】:Why is iframe.contentWindow == null?为什么 iframe.contentWindow == null? 【发布时间】:2012-08-25 08:29:33 【问题描述】:

我使用以下代码动态创建 iframe。

var iframe_jquery = $("<iframe>")
    .addClass("foo")
    .appendTo(container); // container is a jQuery object containing a <div> which already exists

然后,我想访问它的 contentWindow,但是它是空的:

var iframe = iframe_jquery.get(0);
if (iframe) // iFrame exists
    console.log(iframe.contentWindow); // Prints "null"
    var doc = iframe.contentWindow.document; // NullpointerException

所以我想:“也许 iframe 还没有准备好?”所以我尝试了:

iframe_jquery.ready(function()
    var iframe = iframe_jquery.get(0);
    console.log(iframe.contentWindow); // Prints "null"
    var doc = iframe.contentWindow.document; // NullpointerException
);

同样的结果。

怎么了?

【问题讨论】:

您的代码运行良好 here。您的代码中的“容器”是什么? 哦,我明白了——这就是问题所在。 您需要确保 container 已经是活动 DOM 的一部分,如果它是另一个尚未放置在文档中的动态创建的元素,您会遇到这个问题。 【参考方案1】:

上周我在玩 iframe(构建 rtf 编辑器)时遇到了这个问题,是的,它还没有准备好。

我想如果我把它放在.ready() 中,它会起作用,但是.ready() 是当 DOM 准备好时,而不是当 iframe 加载其内容时,所以我最终用 jQuery @987654323 包装我的代码@。

所以试试这个:

$(function ()   
    $("#myiframe").load(function ()                         
        frames["myframe"].document.body.innerhtml = htmlValue;
    );
); 

希望对你有帮助

【讨论】:

有趣的是,我在加载的框架中放了一个按钮,触发了相同的“iframe.contentWindow”,但它也是空的。所以 iframe.contentWindow 根本不起作用。我对吗? (我知道 iframe 不为空) load 事件绝对应该工作......但有时在 Chrome/webkit 中不起作用:( 但对我来说,.ready() 有效,.load() 失败【参考方案2】:

问题是你的&lt;iframe&gt; 在真正添加到页面的实际DOM 之前不会是“真实的”。 Here is a fiddle to demonstrate..

【讨论】:

似乎我无法理解:我可以看到 iframe,该 iframe 是如何未添加到实际 DOM 中的? @Igor 你应该问一个新问题;我不知道你的代码是什么样子的。【参考方案3】:

根据浏览器的不同,访问document&lt;iframe&gt; 可能会有所不同。

以下是如何处理的示例:

if (iframe.contentDocument) // FF Chrome
  doc = iframe.contentDocument;
else if ( iframe.contentWindow ) // IE
  doc = iframe.contentWindow.document;

【讨论】:

contentWindow 属性几乎无处不在,我想。旧版本的IE缺少的是contentDocument 不,不是这样。我只在 iPhone 的默认浏览器和应用程序的不同部分测试我发布的代码有效。【参考方案4】:

您还可以通过设置它的 onload 属性来创建一个在 iframe 完成加载时执行的函数。

【讨论】:

这里接受的答案使用“load”事件(“onload”属性会简单地连接到该事件)。似乎这是公认的答案,加上两个额外的字符。【参考方案5】:

书签版本

只是出于好奇,我想我会把它放在一起。记住 iframe 和加载事件在不同的浏览器上不能很好地配合(主要是旧的、崩溃的、应该死的浏览器)...加上不完全确定 jQuery 是如何解决这个问题的...我的大脑认为这会得到更好的支持(无论是否存在)

$(function()
  /// bind a listener for the bespoke iframeload event
  $(window).bind('iframeload', function()
    /// access the contents of the iframe using jQuery notation
    iframe.show().contents().find('body').html('hello');
  );
  /// create your iframe
  var iframe = $('<iframe />')
        /// by forcing our iframe to evaluate javascript in the path, we know when it's ready
        .attr('src', 'javascript:(function()tryp=window.parent;p.jQuery(p).trigger(\'iframeload\');catch(ee);)();')
        /// insert the iframe into the live DOM
        .appendTo('body');
);

采用这种方法的原因是,通常从 iframe 内部触发加载事件要好得多。但这意味着将适当的文档加载到 iframe 中,因此对于动态 iframe,这有点乏味。这是加载文档和不加载文档之间的一种混合。

以上内容适用于我迄今为止测试过的所有内容 - 是的,你是对的 - 这有点荒谬,不是面向未来的,可能还有其他带有负面含义的东西;)

关于这篇文章,我要说的一个积极的事情是,它介绍了使用.contents() 来访问 iframe 的文档,这至少有点用处......

【讨论】:

以上是关于为啥 iframe.contentWindow == null?的主要内容,如果未能解决你的问题,请参考以下文章

调试 iframe contentWindow 时 Chrome 开发工具崩溃

如何在跨域中获取 iframe contentWindow 高度

iframe 内容窗口

获取IFrame的文档元素

iframe 简单使用

iframe父子页面通信