iFrame src 更改事件检测?

IT技术 javascript jquery iframe onload
2021-01-26 11:03:48

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

如果 iframe src 与以前相同,我最后的手段是进行 1 秒的间隔测试,但是执行这种 hacky 解决方案会很糟糕。

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

6个回答

您可能想要使用该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>
this.contentWindow.location.href 将不起作用,因为您正在执行跨源请求。:( 现在所有浏览器都限制了这一点。
2021-03-15 11:03:48
你的意思是 this.contentWindow.location.href
2021-03-16 11:03:48
当我这样做时,this.contentWindow.location.href我得到Permission denied to access property 'href'
2021-03-30 11:03:48
@Daniel Vassallo 假设您在希望处理安全问题时采用这种方法,难道有人不能只覆盖 onLoad 事件然后更改 iframe 内容吗?
2021-04-02 11:03:48
更正:this.contentWindow.location可用于其他域。Eventhis.contentWindow.location.href可用于其他域,但只能用于写入。然而,阅读this.contentWindow.location.href仅限于同一领域。
2021-04-03 11:03:48

基于 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

@stracigh,这是正确的,每次框架加载时都会触发该事件,因此在初始页面加载时也是如此。如果您不想第一次触发您的代码,您必须以某种方式检测这是您的第一帧加载和返回。
2021-03-11 11:03:48
这有效并检测内容何时加载,我需要一种方法来检测 src 何时发生变化。类似于 beforeLoad(激活加载器)
2021-03-14 11:03:48
不完全按计划工作。它在初始页面加载时触发警报。根据您对此代码的计划(对我而言,我正在为表单提交页面上的对话框设置动画),此解决方案将不起作用。
2021-03-24 11:03:48
正如@stacigh 所指出的,它会在父页面加载时触发一次事件。如果您在该函数外部声明一个计数器并在内部读取它,那么您可以在此之后检测更改。您将在 onload 处理程序内增加 counter 加上 have if (counter > 1) { // do something on iframe actual change }(假设计数器在开始时设置为 0)
2021-03-28 11:03:48
@FooBar,是的,它确实可以跨域工作,实际上这就是我使用它的目的。但是,当该页面位于另一个域上时,您无法使用 javascript 访问 iFrame 中的页面。
2021-04-06 11:03:48

如果您无法控制页面并希望观看某种更改,那么现代方法是使用 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 上

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

@PaulRoub 删除了 jsfiddle 链接(一定是复制/粘贴错误)并将代码作为片段包含在内。
2021-03-17 11:03:48
然后更改 上的选项observe这只是一个例子。
2021-03-23 11:03:48
但在我的情况下,frame.contentDocument.URL 更改(从框架内的链接)而不是 src。我可以看吗?
2021-03-29 11:03:48
不确定,最好写一个我认为的问题。
2021-04-02 11:03:48
如果我使用 Web 组件并且我的自定义组件之一具有 src 属性怎么办?我想这会不小心捡到它。
2021-04-04 11:03:48

注意:该代码段仅在 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 更改。

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

我也用这段代码做了一个要点您也可以查看我的另一个答案它深入探讨了它的工作原理。

在 Chrome 95 中使用 stackoverflow 中的“运行代码片段”按钮运行此代码片段会向我显示此错误:{“消息”:“未捕获的安全错误:阻止了原始框架为“null”的框架无法访问跨源框架。 ", "filename": " stacksnippets.net/js ", "lineno": 24, "colno": 30 }
2021-03-25 11:03:48

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);
    }