gpt4 book ai didi

javascript - 如何检测 iframe 何时已加载

转载 作者:行者123 更新时间:2023-12-03 21:31:22 26 4
gpt4 key购买 nike

如果在 iframe 完成加载后附加 $('#someIframe').load(function(){...}) ,它似乎不会触发。那是对的吗?

我真正想要的是有一个在 iframe 加载时或之后始终调用一次的函数。为了更清楚地说明这一点,这里有两种情况:

  • Iframe 尚未加载:加载后运行回调函数。
  • Iframe 已加载:立即运行回调。

我该怎么做?

最佳答案

我用头撞墙,直到我发现这里发生了什么。

背景信息

  • 如果 iframe 已加载,则无法使用 .load()(事件永远不会触发)
  • 不支持在 iframe 元素上使用 .ready() ( reference ),即使 iframe 尚未加载,也会立即调用回调
  • 只有在控制 iframe 内的 load 时才可以使用 postMessage 或调用容器函数
  • 在容器上使用 $(window).load() 还会等待其他资源加载,例如图像和其他 iframe。如果您只想等待特定的 iframe,这不是一个解决方案
  • 在 Chrome 中检查 readyState 是否已触发 onload 事件是没有意义的,因为 Chrome 会使用“about:blank”空页面初始化每个 iframe。此页面的 readyState 可能是 complete,但它不是您期望的页面的 readyState(src 属性) )。

解决方案

以下内容是必要的:

  1. 如果 iframe 尚未加载,我们可以观察 .load() 事件
  2. 如果 iframe 已加载,我们需要检查 readyState
  3. 如果readyStatecomplete,我们通常可以假设iframe已经加载。但是,由于 Chrome 的上述行为,我们还需要检查它是否是空页面的 readyState
  4. 如果是这样,我们需要在一段时间内观察readyState,以检查实际文档(与src属性相关)是否完整

我已经用以下函数解决了这个问题。它已(转译为 ES5)在

中成功测试
  • Chrome 49
  • Safari 5
  • 火狐45
  • IE 8、9、10、11
  • 边缘 24
  • iOS 8.0(“Safari 移动版”)
  • Android 4.0(“浏览器”)

函数取自 jquery.mark

/**
* Will wait for an iframe to be ready
* for DOM manipulation. Just listening for
* the load event will only work if the iframe
* is not already loaded. If so, it is necessary
* to observe the readyState. The issue here is
* that Chrome will initialize iframes with
* "about:blank" and set its readyState to complete.
* So it is furthermore necessary to check if it's
* the readyState of the target document property.
* Errors that may occur when trying to access the iframe
* (Same-Origin-Policy) will be catched and the error
* function will be called.
* @param {jquery} $i - The jQuery iframe element
* @param {function} successFn - The callback on success. Will
* receive the jQuery contents of the iframe as a parameter
* @param {function} errorFn - The callback on error
*/
var onIframeReady = function($i, successFn, errorFn) {
try {
const iCon = $i.first()[0].contentWindow,
bl = "about:blank",
compl = "complete";
const callCallback = () => {
try {
const $con = $i.contents();
if($con.length === 0) { // https://git.io/vV8yU
throw new Error("iframe inaccessible");
}
successFn($con);
} catch(e) { // accessing contents failed
errorFn();
}
};
const observeOnload = () => {
$i.on("load.jqueryMark", () => {
try {
const src = $i.attr("src").trim(),
href = iCon.location.href;
if(href !== bl || src === bl || src === "") {
$i.off("load.jqueryMark");
callCallback();
}
} catch(e) {
errorFn();
}
});
};
if(iCon.document.readyState === compl) {
const src = $i.attr("src").trim(),
href = iCon.location.href;
if(href === bl && src !== bl && src !== "") {
observeOnload();
} else {
callCallback();
}
} else {
observeOnload();
}
} catch(e) { // accessing contentWindow failed
errorFn();
}
};

工作示例

由两个文件组成(index.html 和 iframe.html):index.html:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Parent</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-1.12.2.min.js"></script>
<script>
$(function() {

/**
* Will wait for an iframe to be ready
* for DOM manipulation. Just listening for
* the load event will only work if the iframe
* is not already loaded. If so, it is necessary
* to observe the readyState. The issue here is
* that Chrome will initialize iframes with
* "about:blank" and set its readyState to complete.
* So it is furthermore necessary to check if it's
* the readyState of the target document property.
* Errors that may occur when trying to access the iframe
* (Same-Origin-Policy) will be catched and the error
* function will be called.
* @param {jquery} $i - The jQuery iframe element
* @param {function} successFn - The callback on success. Will
* receive the jQuery contents of the iframe as a parameter
* @param {function} errorFn - The callback on error
*/
var onIframeReady = function($i, successFn, errorFn) {
try {
const iCon = $i.first()[0].contentWindow,
bl = "about:blank",
compl = "complete";
const callCallback = () => {
try {
const $con = $i.contents();
if($con.length === 0) { // https://git.io/vV8yU
throw new Error("iframe inaccessible");
}
successFn($con);
} catch(e) { // accessing contents failed
errorFn();
}
};
const observeOnload = () => {
$i.on("load.jqueryMark", () => {
try {
const src = $i.attr("src").trim(),
href = iCon.location.href;
if(href !== bl || src === bl || src === "") {
$i.off("load.jqueryMark");
callCallback();
}
} catch(e) {
errorFn();
}
});
};
if(iCon.document.readyState === compl) {
const src = $i.attr("src").trim(),
href = iCon.location.href;
if(href === bl && src !== bl && src !== "") {
observeOnload();
} else {
callCallback();
}
} else {
observeOnload();
}
} catch(e) { // accessing contentWindow failed
errorFn();
}
};

var $iframe = $("iframe");
onIframeReady($iframe, function($contents) {
console.log("Ready to got");
console.log($contents.find("*"));
}, function() {
console.log("Can not access iframe");
});
});
</script>
<iframe src="iframe.html"></iframe>
</body>
</html>

iframe.html:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Child</title>
</head>
<body>
<p>Lorem ipsum</p>
</body>
</html>

您还可以将 index.html 中的 src 属性更改为例如“http://example.com/”。只是玩玩而已。

关于javascript - 如何检测 iframe 何时已加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17158932/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com