乐闻世界logo
搜索文章和话题

How to detect when an iframe starts to load new url?

9 个月前提问
5 个月前修改
浏览次数167

3个答案

1
2
3

在检测iframe开始加载新URL时,通常会用到JavaScript中的事件监听器。以下是一些方法,可以用来监测iframe何时开始加载新的URL:

方法1:使用 onload 事件

要检测iframe是否完成了新URL的加载,可以监听iframeonload事件。但是,它只能告诉我们iframe什么时候加载完成,并不能直接告诉我们何时开始。不过,我们可以在设置新的src属性之前初始化一些操作,来模拟“开始加载”的检测:

javascript
var iframe = document.getElementById('myIframe'); // 当`iframe`开始加载新URL时执行的函数 function onIframeStartLoad() { console.log('开始加载新的URL...'); } // 当`iframe`完成加载新URL时执行的函数 function onIframeLoad() { console.log('新的URL加载完成'); } // 监听`iframe`的`onload`事件 iframe.onload = onIframeLoad; // 更改`iframe`的`src`属性以开始加载新的URL iframe.src = 'https://example.com'; // 在设置`src`之前,我们知道加载即将开始 onIframeStartLoad(); // 手动调用开始加载的函数

方法2:使用 addEventListener 方法

我们可以使用addEventListener来给iframe添加load事件监听器,这更适合现代浏览器和动态事件管理:

javascript
var iframe = document.getElementById('myIframe'); iframe.addEventListener('load', function() { console.log('新的URL加载完成'); }); // 在更改`iframe`的`src`之前,我们可以执行某些操作 console.log('开始加载新的URL...'); iframe.src = 'https://example.com';

方法3:使用 MutationObserver

如果您希望检测iframesrc属性何时被改变(而不一定是加载完成),可以使用MutationObserver。这允许您监视DOM更改,例如属性的改变:

javascript
var iframe = document.getElementById('myIframe'); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'attributes' && mutation.attributeName === 'src') { console.log('iframe src 属性改变,新的URL开始加载'); } }); }); observer.observe(iframe, { attributes: true // 配置观察者只观察属性的变动 }); // 更改`iframe`的`src`属性 iframe.src = 'https://example.com';

方法4:使用 beforeunload 事件

在一些特定的情况下,你可能想要在原有页面即将卸载时检测到iframe开始加载新页面的行为。在这种情况下,可以使用beforeunload事件:

javascript
var iframe = document.getElementById('myIframe'); iframe.contentWindow.onbeforeunload = function() { console.log('iframe 即将开始加载新页面'); }; // 更改`iframe`的`src`属性 iframe.src = 'https://example.com';

请注意,这种方法可能会受到跨域政策的限制,因为它需要访问iframecontentWindow对象。

总结一下,通常来说,我们可以通过监听iframeload事件或者使用MutationObserver来检测iframe何时开始加载新的URL。确保在设置新的src属性之前进行必要的操作,可以帮助我们定位到加载的开始时机。在实际的应用中,选择哪种方法取决于具体的需求和场景。

2024年6月29日 12:07 回复

我找到了一个更好的解决方案,如果 iframe 和容器页面同源,则不必将额外的代码放入内部页面:

shell
<iframe src="same-origin.com" onload="content_finished_loading(this)"></iframe> <script> var indicator = document.querySelector('.loading-indicator'); var content_start_loading = function() { indicator.style.display = 'block'; }; var content_finished_loading = function(iframe) { indicator.style.display = 'none'; // inject the start loading handler when content finished loading iframe.contentWindow.onunload = content_start_loading; }; </script>
2024年6月29日 12:07 回复

我想出了以下解决方案 - 这是唯一可能的,因为我们控制 iframe 内容和主机窗口的内容

在 iframe 内,我们将以下脚本添加到页面页脚(所有页面都使用相同的模板,因此这是对单个文件的更改)

shell
<script> window.onunload = function() { // Notify top window of the unload event window.top.postMessage('iframe_change', '*'); }; </script>

在主机窗口内,我们添加此脚本来监视 iframe 状态

shell
function init_content_monitor() { var content = jQuery('.iframe'); // The user did navigate away from the currently displayed iframe page. Show an animation var content_start_loading = function() { alert ('NOW: show the animation'); } // the iframe is done loading a new page. Hide the animation again var content_finished_loading = function() { alert ('DONE: hide the animation'); } // Listen to messages sent from the content iframe var receiveMessage = function receiveMessage(e){ var url = window.location.href, url_parts = url.split("/"), allowed = url_parts[0] + "//" + url_parts[2]; // Only react to messages from same domain as current document if (e.origin !== allowed) return; // Handle the message switch (e.data) { case 'iframe_change': content_start_loading(); break; } }; window.addEventListener("message", receiveMessage, false); // This will be triggered when the iframe is completely loaded content.on('load', content_finished_loading); }
2024年6月29日 12:07 回复

你的答案