如何在不阻塞 onload 或等待 onload 的情况下加载 iframe

Mic*_*haw 6 html javascript performance iframe

假设我有这个页面:

<h1>Hello, world!</h1>
<iframe src="https://example.com/test.html"></iframe>
Run Code Online (Sandbox Code Playgroud)

test.html 包含以下内容:

<img src="huge.png" />
Run Code Online (Sandbox Code Playgroud)

huge.png 由于某种原因是 100mb。

我无法控制 test.html,但我必须在我的页面中包含 iframe。

有没有办法在不加载 iframe 的情况下加载 iframe

  1. 阻止我页面的onload事件或
  2. 等到我的页面onload事件设置 iframe 的src属性

我想要#1,因为我不希望页面上的 JS 不得不等待 example.com 的慢速图像。

我想要#2,因为我想尽快开始加载example.com 的内容。

有两个类似的问题。

这就是它们不重复的原因:

  1. 也不清楚“阻止”加载意味着什么 - 我指定了onload事件。
  2. 两者都没有指定我无法控制 iframe 的内容(#2 上的第一个答案假设)。
  3. 两者都没有指定在src之后设置属性onload不是一个选项(#1 上的几个答案假设)。

虽然这些问题的答案可能会回答这个问题,但两者的措辞都不是答案必须回答这个问题。

Chr*_*ras 7

您可以按照charlietfl在评论中的建议使用Window: DOMContentLoaded 事件;它不会被资源/资产加载阻止:

DOMContentLoaded事件触发时,最初的HTML文档已被完全加载和分析,而无需等待样式表,图片和子帧完成加载。

这是加载具有 2MB JPEG 图像的外部 iFrame 的演示片段;当您运行它时,您会看到DOMContentLoaded在 iFrame 完全加载之前触发并运行自定义 Javascript;然后当 iFrame 加载完成时,load调用 iFrame 上的事件并更新状态文本。

// On DOMContentLoaded set status text and start an ASCII animation
window.addEventListener('DOMContentLoaded', (event) => {
  document.getElementById('js-status').textContent = 'DOM fully loaded and parsed; staring JS code';

  const animation = new animascii({
      src: [
          ["0-----", "-----0"],
          ["-0----", "----0-"],
          ["--0---", "---0--"],
          ["---0--", "--0---"],
          ["----0-", "-0----"],
          ["-----0", "0-----"]
      ],
      display: document.getElementById("ascii-animation"),
      repeat: -1,
      delay: 120,
      font_size: 20
  }, function() {
      alert("Done!");
  });
});

// On iframe load event set status text
document.getElementsByTagName('iframe')[0].addEventListener('load', function() {
  document.getElementById('iframe-status').textContent = 'IFrame fully loaded';
});
Run Code Online (Sandbox Code Playgroud)
iframe { width: 600px; height: 400px; }
h2 span { color: blue; }
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rot.js/0.6.0/rot.min.js"></script>
<script src="https://www.cssscript.com/demo/ascii-animation-library-pure-javascript-animascii/animascii.js"></script>

<h2>DOM/JS status: <span id="js-status">(loading...)</span></h2>
<h2>IFrame status: <span id="iframe-status">(loading...)</span></h2>

<h3>Demo JS to check that JS is running after DOMContentLoaded and before iFrame finish loading</h3>
<div id="ascii-animation"></div>

<iframe src="https://zikro.gr/dbg/so/53583045/iframe.php"></iframe>
Run Code Online (Sandbox Code Playgroud)

当然,您可以将 iFramesrc属性设置为load,但这已经包含在您链接的问题中:

window.addEventListener('load', (event) => {
  document.getElementById('js-status').textContent = 'DOM fully loaded and parsed; staring JS code';
  document.getElementById('iframe-status').textContent = '(loading...)';
  document.getElementsByTagName('iframe')[0].setAttribute('src', 'https://zikro.gr/dbg/so/53583045/iframe.php');
});

document.getElementsByTagName('iframe')[0].addEventListener('load', (event) => {
  document.getElementById('iframe-status').textContent = 'IFrame fully loaded';
});
Run Code Online (Sandbox Code Playgroud)
iframe { width: 600px; height: 400px; }
h2 span { color: blue; }
Run Code Online (Sandbox Code Playgroud)
<h2>DOM/JS status: <span id="js-status">(loading...)</span></h2>
<h2>IFrame status: <span id="iframe-status">(not started yet)</span></h2>

<iframe></iframe>
Run Code Online (Sandbox Code Playgroud)


Emi*_*röm 7

在现代浏览器中,您所需要做的就是添加loading="lazy"到 iframe 中。

<iframe src="test.html" loading="lazy" />
Run Code Online (Sandbox Code Playgroud)

并非所有地方都支持它,但也许足以满足您的情况?


Jac*_*opo 5

一个不同且更简单的技巧:照常加载,但还包括

<link rel="prefetch" href="https://example.com/test.html">
Run Code Online (Sandbox Code Playgroud)

在您页面的<head>.

浏览器将开始为您获取test.html(或huge.png)

它甚至不需要 iframe 存在,您可以将其放在任何页面中。如果需要,您可以让浏览器在外部资源到达需要外部资源的特定页面之前就开始加载它。

当然,详细的时间取决于浏览器的决定,但归根结底,这对于所有异步请求都是正确的——您可以将其放在prefetch文档类型内容之后。