简体   繁体   English

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

[英]How to load an iframe without blocking onload or waiting for onload

Suppose I have this page:假设我有这个页面:

<h1>Hello, world!</h1>
<iframe src="https://example.com/test.html"></iframe>

And test.html contains this: test.html 包含以下内容:

<img src="huge.png" />

huge.png is 100mb for some reason.由于某种原因, huge.png是 100mb。

I have no control over test.html, but I must include the iframe in my page.我无法控制 test.html,但我必须在我的页面中包含 iframe。

Is there a way to load the iframe without有没有办法在不加载 iframe 的情况下加载 iframe

  1. blocking my page's onload event OR阻止我页面的onload事件或
  2. waiting until my page's onload event to set the iframe's src attribute等到我的页面的onload事件设置 iframe 的src属性

I want #1 because I don't want JS on my page to have to wait for example.com's slow image.我想要#1,因为我不希望页面上的 JS 不得不等待 example.com 的慢速图像。

I want #2 because I want to start loading example.com's content ASAP.我想要#2,因为我想尽快开始加载example.com 的内容。

There are two similar questions.有两个类似的问题。

This is why they aren't duplicates:这就是它们不重复的原因:

  1. Neither is clear what it means to "block" loading - I specify the onload event.也不清楚“阻止”加载意味着什么 - 我指定了onload事件。
  2. Neither specifies that I don't have control over the iframe's contents (which the first answer on #2 assumes).两者都没有指定我无法控制 iframe 的内容(#2 上的第一个答案假设)。
  3. Neither specifies that setting the src attribute after onload is not an option (which several answers on #1 assume).两者都没有指定在onload之后设置src属性不是一个选项(#1 上的几个答案假设)。

While it's possible that answers to those questions could answer this one, neither is worded in such a way that the answer must answer this question.虽然这些问题的答案可能会回答这个问题,但两者的措辞都不是答案必须回答这个问题。

You can use Window: DOMContentLoaded event as suggested by charlietfl in the comments;您可以按照charlietfl在评论中的建议使用Window: DOMContentLoaded 事件 it does not get blocked by resources/assets loading:它不会被资源/资产加载阻止:

The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. DOMContentLoaded事件在初始 HTML 文档完全加载和解析后触发,无需等待样式表、图像和子框架完成加载。

Here is a demo snippet that loads an external iFrame that has a 2MB JPEG image;这是加载具有 2MB JPEG 图像的外部 iFrame 的演示片段; when you run it, you'll see that DOMContentLoaded get to trigger before the iFrame fully loads and it runs custom Javascript;当您运行它时,您会看到DOMContentLoaded在 iFrame 完全加载之前触发并运行自定义 Javascript; then when the iFrame is done loading, the load event on the iFrame is called and we update a status text.然后当 iFrame 完成加载时,iFrame 上的load事件被调用,我们更新状态文本。

 // 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'; });
 iframe { width: 600px; height: 400px; } h2 span { color: blue; }
 <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>

Of course you can set the iFrame src attribute on load , but that is already covered by the questions you're linking:当然,您可以在load上设置 iFrame src属性,但这已经包含在您链接的问题中:

 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'; });
 iframe { width: 600px; height: 400px; } h2 span { color: blue; }
 <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>

A different and somewhat-easier trick: do the load as usual, but also include一个不同的、更简单的技巧:像往常一样加载,但也包括

<link rel="prefetch" href="https://example.com/test.html">

in your page's <head> .在您页面的<head>

The browser will start fetching test.html (or huge.png) for you .浏览器将开始为您获取 test.html(或巨大的.png)

It doesn't even require the iframe to exist, you can put it in any page.它甚至不需要 iframe 存在,你可以把它放在任何页面中。 If you want, you can have the browser start loading the external resource before it's even on the specific page that needs it.如果需要,您可以让浏览器在外部资源加载到需要它的特定页面之前就开始加载它。

The detailed time depends on the browser's decision, of course, but at the end of the day that's true for all async requests -- and you can put that prefetch first thing after the doctype stuff.当然,详细时间取决于浏览器的决定,但归根结底,所有异步请求都是如此——您可以将prefetch放在 doctype 内容之后。

In modern browsers all you need to do is add loading="lazy" to your iframe.在现代浏览器中,您需要做的就是在 iframe 中添加loading="lazy"

<iframe src="test.html" loading="lazy" />

It's not supported everywhere , but maybe enough for your case?并非所有地方都支持它,但对于您的情况可能已经足够了?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM