218

假设我无法控制 iframe 中的内容,有什么方法可以通过父页面检测到其中的 src 更改?也许某种onload?

如果 iframe src 与以前相同,我最后的手段是进行 1 秒的间隔测试,但是这样做会很糟糕。

如果有帮助,我正在使用 jQuery 库。

4

7 回答 7

229

您可能想要使用该onLoad事件,如下例所示:

<iframe src="http://www.google.com/" onLoad="alert('Test');"></iframe>

只要 iframe 中的位置发生变化,就会弹出警报。它适用于所有现代浏览器,但可能不适用于一些非常旧的浏览器,如 IE5 和早期的 Opera。(来源

如果 iframe 显示的是与 parent 相同域中的页面,您将能够使用 访问该位置contentWindow.location,如下例所示:

<iframe src="/test.html" onLoad="alert(this.contentWindow.location);"></iframe>
于 2010-03-11T22:10:50.230 回答
59

基于 JQuery < 3 的答案

$('#iframeid').load(function(){
    alert('frame has (re)loaded');
});

正如 subharb 所提到的,从 JQuery 3.0 开始,这需要更改为:

$('#iframe').on('load', function() {
    alert('frame has (re)loaded ');
});

https://jquery.com/upgrade-guide/3.0/#break-change-load-unload-and-error-removed

于 2012-10-22T14:01:18.397 回答
44

如果您无法控制页面并希望观察某种变化,那么现代方法是使用MutationObserver

它的使用示例,观察src属性的变化iframe

new MutationObserver(function(mutations) {
  mutations.some(function(mutation) {
    if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
      console.log(mutation);
      console.log('Old src: ', mutation.oldValue);
      console.log('New src: ', mutation.target.src);
      return true;
    }

    return false;
  });
}).observe(document.body, {
  attributes: true,
  attributeFilter: ['src'],
  attributeOldValue: true,
  characterData: false,
  characterDataOldValue: false,
  childList: false,
  subtree: true
});

setTimeout(function() {
  document.getElementsByTagName('iframe')[0].src = 'http://jsfiddle.net/';
}, 3000);
<iframe src="http://www.google.com"></iframe>

3秒后输出

MutationRecord {oldValue: "http://www.google.com", attributeNamespace: null, attributeName: "src", nextSibling: null, previousSibling: null…}
Old src:  http://www.google.com
New src:  http://jsfiddle.net/ 

jsFiddle 上

在此处发布答案,因为原始问题已作为此问题的副本关闭。

于 2014-07-13T21:00:04.357 回答
23

注意:该片段仅在 iframe 具有相同来源时才有效。

其他答案提出了该load事件,但它在 iframe 中的新页面加载后触发。您可能需要在 URL 更改后立即收到通知,而不是在加载新页面后。

这是一个简单的 JavaScript 解决方案:

function iframeURLChange(iframe, callback) {
    var unloadHandler = function () {
        // Timeout needed because the URL changes immediately after
        // the `unload` event is dispatched.
        setTimeout(function () {
            callback(iframe.contentWindow.location.href);
        }, 0);
    };

    function attachUnload() {
        // Remove the unloadHandler in case it was already attached.
        // Otherwise, the change will be dispatched twice.
        iframe.contentWindow.removeEventListener("unload", unloadHandler);
        iframe.contentWindow.addEventListener("unload", unloadHandler);
    }

    iframe.addEventListener("load", attachUnload);
    attachUnload();
}

iframeURLChange(document.getElementById("mainframe"), function (newURL) {
    console.log("URL changed:", newURL);
});
<iframe id="mainframe" src=""></iframe>

这将成功跟踪src属性更改,以及在 iframe 本身内所做的任何 URL 更改。

在所有现代浏览器中测试。

我也用这段代码做了一个要点。您也可以查看我的其他答案。它有点深入了解它是如何工作的。

于 2017-12-06T13:48:16.897 回答
7

iframe 始终保留父页面,您应该使用它来检测您在 iframe 中的哪个页面:

html代码:

<iframe id="iframe" frameborder="0" scrolling="no" onload="resizeIframe(this)" width="100%" src="www.google.com"></iframe>

JS:

    function resizeIframe(obj) {
        alert(obj.contentWindow.location.pathname);
    }
于 2016-10-05T09:21:05.563 回答
4

从 Jquery 3.0 版开始,您可能会收到错误消息

TypeError:url.indexOf 不是函数

可以通过以下方式轻松修复

$('#iframe').on('load', function() {
    alert('frame has (re)loaded ');
});
于 2017-12-18T09:58:01.090 回答
2

这是Commerce SagePayCommerce Paypoint Drupal 模块中使用的方法,它基本上document.location.href与旧值进行比较,首先加载自己的 iframe,然后加载外部 iframe。

所以基本上这个想法是将空白页面加载为具有自己的 JS 代码和隐藏表单的占位符。然后父 JS 代码将提交#action指向外部 iframe 的隐藏表单。一旦发生重定向/提交,仍在该页面上运行的 JS 代码可以跟踪您的document.location.href值更改。

这是 iframe 中使用的示例 JS:

;(function($) {
  Drupal.behaviors.commercePayPointIFrame = {
    attach: function (context, settings) {
      if (top.location != location) {
        $('html').hide();
        top.location.href = document.location.href;
      }
    }
  }
})(jQuery);

这是父页面中使用的JS:

;(function($) {
  /**
   * Automatically submit the hidden form that points to the iframe.
   */
  Drupal.behaviors.commercePayPoint = {
    attach: function (context, settings) {
      $('div.payment-redirect-form form', context).submit();
      $('div.payment-redirect-form #edit-submit', context).hide();
      $('div.payment-redirect-form .checkout-help', context).hide();
    }
  }
})(jQuery);

然后在临时空白登录页面中,您需要包含将重定向到外部页面的表单。

于 2016-03-16T15:49:08.513 回答