150

当 IFRAME 完成加载时,我需要执行回调。我无法控制 IFRAME 中的内容,因此无法从那里触发回调。

这个 IFRAME 是以编程方式创建的,我需要在回调中将其数据作为变量传递,以及销毁 iframe。

有任何想法吗?

编辑:

这是我现在拥有的:

function xssRequest(url, callback)
{
    var iFrameObj = document.createElement('IFRAME');
    iFrameObj.src = url;            
    document.body.appendChild(iFrameObj);   

    $(iFrameObj).load(function() 
    {
        document.body.removeChild(iFrameObj);
        callback(iFrameObj.innerHTML);
    });
}

此回调在 iFrame 加载之前进行,因此回调没有返回数据。

4

11 回答 11

49

首先,通过函数名称xssRequest听起来您正在尝试跨站点请求 - 如果这是正确的,您将无法读取 iframe 的内容。

另一方面,如果 iframe 的 URL 在您的域上,您可以访问正文,但我发现如果我使用超时来删除 iframe,则回调可以正常工作:

// possibly excessive use of jQuery - but I've got a live working example in production
$('#myUniqueID').load(function () {
  if (typeof callback == 'function') {
    callback($('body', this.contentWindow.document).html());
  }
  setTimeout(function () {$('#frameId').remove();}, 50);
});
于 2008-10-16T18:31:38.953 回答
37

我正在使用 jQuery,令人惊讶的是,这似乎加载了,因为我刚刚测试并加载了一个沉重的页面,并且在看到 iframe 加载之前我没有收到警报几秒钟:

$('#the_iframe').load(function(){
    alert('loaded!');
});

因此,如果您不想使用 jQuery,请查看他们的源代码,看看此函数与 iframe DOM 元素的行为是否不同,稍后我会自己查看它,因为我有兴趣并在此处发布。我也只在最新的 chrome 中测试过。

于 2013-05-03T16:12:24.027 回答
8

在将 word docs 和 pdf 等文档流式传输到 iframe 并找到一个运行良好的解决方案的情况下,我不得不这样做。关键是处理onreadystatechangediframe 上的事件。

假设您的框架的名称是“myIframe”。首先在您的代码启动中的某个地方(我在 iframe 之后的任何地方内联)添加类似这样的内容来注册事件处理程序:

document.getElementById('myIframe').onreadystatechange = MyIframeReadyStateChanged;

我无法在 iframe 上使用 onreadystatechage 属性,我不记得为什么,但该应用程序必须在 IE 7 和 Safari 3 中运行,所以这可能是一个因素。

以下是如何获取完整状态的示例:

function MyIframeReadyStateChanged()
{
    if(document.getElementById('myIframe').readyState == 'complete')
    {
        // Do your complete stuff here.
    }
}
于 2008-12-05T05:33:44.137 回答
8

您的 iframe 的 innerHTML 是空白的,因为您的 iframe 标记没有包围父文档中的任何内容。为了从 iframe 的 src 属性引用的页面中获取内容,您需要访问 iframe 的 contentDocument 属性。但是,如果 src 来自不同的域,则会引发异常。这是一项安全功能,可防止您在其他人的页面上执行任意 JavaScript,这会造成跨站点脚本漏洞。这是一些示例代码,说明了我在说什么:

<script src="http://prototypejs.org/assets/2009/8/31/prototype.js" type="text/javascript"></script>

<h1>Parent</h1>

<script type="text/javascript">
function on_load(iframe) {
  try {
    // Displays the first 50 chars in the innerHTML of the
    // body of the page that the iframe is showing.
    // EDIT 2012-04-17: for wider support, fallback to contentWindow.document
    var doc = iframe.contentDocument || iframe.contentWindow.document;
    alert(doc.body.innerHTML.substring(0, 50));
  } catch (e) {
    // This can happen if the src of the iframe is
    // on another domain
    alert('exception: ' + e);
  }
}
</script>
<iframe id="child" src="iframe_content.html" onload="on_load(this)"></iframe>

为了进一步说明示例,请尝试将其用作 iframe 的内容:

<h1>Child</h1>

<a href="http://www.google.com/">Google</a>

<p>Use the preceeding link to change the src of the iframe
to see what happens when the src domain is different from
that of the parent page</p>
于 2010-02-12T10:32:50.050 回答
7

当 i 框架内容在 IE 上完全加载时,我想隐藏等待的微调器 div,我尝试了 Stackoverflow.Com 中提到的所有解决方案,但没有任何效果。

然后我有了一个想法,当 i 帧内容完全加载时,可能会触发 $(Window) 加载事件。这正是发生的事情。所以,我写了这个小脚本,并且像魔术一样工作:

     $(window).load(function () {
     //alert("Done window ready ");
     var lblWait = document.getElementById("lblWait");
     if (lblWait != null ) {
         lblWait.style.visibility = "false";
         document.getElementById("divWait").style.display = "none";
     }
 });

希望这可以帮助。

于 2014-12-10T08:16:19.070 回答
2

我和你有类似的问题。我所做的是我使用了一个叫做 jQuery 的东西。然后您在 javascript 代码中执行的操作是:

$(function(){ //this is regular jQuery code. It waits for the dom to load fully the first time you open the page.

    $("#myIframeId").load(function(){
       callback($("#myIframeId").html());
       $("#myIframeId").remove();

    });

});

似乎您在从中获取 html 之前删除了 iFrame。现在,我确实看到了一个问题:p

希望这可以帮助 :)。

于 2011-09-10T08:23:47.677 回答
1

我的项目中有一个类似的代码可以正常工作。使我的代码适应您的功能,解决方案可能如下:

function xssRequest(url, callback)
{
    var iFrameObj = document.createElement('IFRAME');
    iFrameObj.id = 'myUniqueID';
    document.body.appendChild(iFrameObj);       
    iFrameObj.src = url;                        

    $(iFrameObj).load(function() 
    {
        callback(window['myUniqueID'].document.body.innerHTML);
        document.body.removeChild(iFrameObj);
    });
}

也许你有一个空的innerHTML,因为(一个或两个原因):1.你应该对body元素使用它2.你已经从你的页面DOM中删除了iframe

于 2008-10-15T13:52:53.307 回答
1

我认为加载事件是正确的。不正确的是您用来从 iframe 内容 dom 中检索内容的方式。

您需要的是 iframe 中加载的页面的 html,而不是 iframe 对象的 html。

您所要做的就是使用iFrameObj.contentDocument. 这将返回 iframe 中加载的页面的 dom,如果它位于当前页面的同一域中。

我会在删除 iframe 之前检索内容。

我已经在 Firefox 和 Opera 中进行了测试。

$(childDom).html()然后我认为您可以使用或检索您的数据$(childDom).find('some selector') ...

于 2009-08-25T13:33:03.917 回答
1

如果 iFrame 已加载或等待 iFrame 完全加载,此函数将立即运行您的回调函数。

这也解决了以下问题:

  1. Chrome 使用一个页面初始化每个 iFrame,该about:blank页面将包含readyState == "complete". 稍后,它会将 `about:blank 替换为实际的 iframe src 值。所以,readyState 的初始值不会代表你实际 iFrame 的 readyState。因此,除了检查 readyState 值之外,此函数还解决了 about:blank 问题。

  2. DOMContentLoaded事件不适用于 iFrame。因此,load如果 iFrame 尚未加载,它会使用事件来运行回调函数。该load事件相当于readyState == "complete"which has been 用于检查 iFrame 是否已加载。因此,在任何情况下,回调函数都会在 iFrame 完全加载后运行。

  3. iFrame src 可以具有重定向,因此加载与原始 src url 不同的页面。此功能也适用于该场景。

将您想要在 iFrame 完成加载时运行的回调函数和<iframe>元素传递给此函数:

function iframeReady(callback, iframeElement) {
    const iframeWindow = iframeElement.contentWindow;
    if ((iframeElement.src == "about:blank" || (iframeElement.src != "about:blank" && iframeWindow.location.href != "about:blank")) && iframeWindow.document.readyState == "complete") {
        callback();
    } else {
        iframeWindow.addEventListener("load", callback);
    }
}
于 2021-10-24T07:49:52.850 回答
0

我过去遇到过完全相同的问题,我发现解决它的唯一方法是将回调添加到 iframe 页面中。当然,这仅在您可以控制 iframe 内容时才有效。

于 2008-10-02T19:34:53.117 回答
-1

使用onload属性将解决您的问题。

这是一个例子。

function a() {
alert("Your iframe has been loaded");
}
<iframe src="https://stackoverflow.com" onload="a()"></iframe>

这是你想要的吗?

点击这里了解更多信息。

于 2018-03-26T08:07:51.540 回答