javascript <body>.onLoad 在渲染完成之前被调用了吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5221416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 16:25:29  来源:igfitidea点击:

Is <body>.onLoad called before rendering is done?

javascripthtml

提问by Mr. Boy

I want to call some JS after the page-load, this may involve a delay and as such I want the page loaded first so content is shown... but it seems that the code in onLoad handler is called beforethe rendering is complete. Is there a better event I can use, which is triggered when the page is 'finished'?

我想在页面加载后调用一些 JS,这可能涉及延迟,因此我希望首先加载页面以便显示内容......但似乎在渲染完成之前调用了 onLoad 处理程序中的代码。有没有更好的事件我可以使用,当页面“完成”时触发?

To clarify, I want to run some JS after the page is rendered on-screen, so a 'post-everything event' really.

澄清一下,我想在页面呈现在屏幕上之后运行一些 JS,所以真的是“发布所有事件”。

回答by Chuck Kollars

There are several points of interest along the time sequence. This generic sequence is a good overview, even though different browsers and versions implement the details a little differently. (This assumes you're using raw Javascript and need to minimize cross-browser issues; with it's comprehensive internal handling of cross-browser issues JQuery is a little different):

沿着时间序列有几个有趣的点。这个通用序列是一个很好的概述,即使不同的浏览器和版本对细节的实现略有不同。(这假设您使用原始 Javascript 并且需要最小化跨浏览器问题;由于它对跨浏览器问题的全面内部处理,JQuery 有点不同):

T0] page-begun-- The browser has started working on the page, but otherwise the environment is in flux. Your JS operations may occur in the wrong context, and simply be flushed away when the right context stabilizes. You probably don't want to try to execute any JS at all.

T0] page-begun-- 浏览器已经开始在页面上工作,但除此之外,环境在不断变化。您的 JS 操作可能发生在错误的上下文中,并且在正确的上下文稳定时简单地将其清除。您可能根本不想尝试执行任何 JS。

T1] "onLoad" event-- [however you get events: addEventListener("Load"..., window.onload=..., etc.] All parts of the page have been identified and downloadedfrom the server and are in the local system's memory. In order for all parts to be identified, some parsing has already occurred. (Note that "load" is a cognate of "download", not "parse" nor "render".)

T1] "onLoad" 事件-- [但是你得到事件:addEventListener("Load"..., window.onload=..., etc.] 页面的所有部分都已经被识别并 从服务器下载并且在本地系统的内存。为了识别所有部分,已经进行了一些解析。(请注意,“加载”是“下载”的同源词,而不是“解析”或“渲染”。)

You now have the right environment and can begin to execute JS code without fear of losing anything. HOWEVER, operations that try to read or manipulate the HTML [getElementById(..., appendChild(..., etc.] may fail in strange ways, or may appear to work but then disappear, or may do something different than you expected.

您现在拥有了正确的环境,可以开始执行 JS 代码而不必担心丢失任何东西。然而,尝试读取或操作 HTML [getElementById(..., appendChild(..., etc.]) 的操作可能会以奇怪的方式失败,或者可能看起来工作但随后消失,或者可能会做一些与您预期不同的事情.

T2] DOM-almost-ready-- This hack is very simple and fully cross browser. Just put your JS <script>...</script> at the very end of your HTML, just before the </body> tag. Most things will work right, although attempts to append to or modify the DOM at the very end of the <body> may produce surprising results. This isn't fully correct, but it works 99% of the time. Given its simplicity and the very high probability of correct operation, this may be the way to go (at least if you don't use JQuery).

T2] DOM-几乎-准备好了--这个hack非常简单并且完全跨浏览器。只需将您的 JS <script>...</script> 放在 HTML 的最后,就在 </body> 标记之前。大多数事情都会正常工作,尽管尝试在 <body> 的最后追加或修改 DOM 可能会产生令人惊讶的结果。这并不完全正确,但它在 99% 的情况下都有效。鉴于其简单性和正确操作的可能性非常高,这可能是可行的方法(至少在您不使用 JQuery 的情况下)。

T3] DOM-ready-- [however you get events: addEventListener("DOMContentLoaded"..., window.ondomcontentloaded=..., etc.] At this point the HTML has been completely parsed and JS is 100% available, including all functions that read or manipulate the HTML [getElementById(..., appendChild(..., etc.].

T3] DOM-ready-- [但是你得到事件: addEventListener("DOMContentLoaded"..., window.ondomcontentloaded=..., etc.] 此时 HTML 已经完全解析并且 JS 是 100% 可用的,包括所有读取或操作 HTML 的函数 [getElementById(..., appendChild(..., etc.])。

T4] Render-done-- The browser is finished displaying the content on the screen. There is NOTany such event or any reasonable cross-browser version-agnostic way to detect this situation. That's just as well, as you probably don't really want this anyway. If the browser has already displayed the page on the screen and thenyou manipulate the DOM, you'll get a "flash", where both the before and the after are visible on the screen at least briefly. What you probably really want is the point where you can execute arbitrary JS code; that's the previous(T3] DOM-ready) point in time.

T4] Render-done--浏览器完成在屏幕上显示内容。有不是任何这样的事件或任何合理的跨浏览器的版本无关的方式来检测这种情况。那也一样,因为无论如何你可能并不真正想要这个。如果浏览器已经在屏幕上显示了页面,然后你操作 DOM,你会得到一个“flash”,之前和之后都至少在屏幕上短暂可见。您可能真正想要的是可以执行任意 JS 代码的点;那是之前的(T3] DOM-ready) 时间点。

回答by Felix Kling

Either attach a callback to window.onload

要么将回调附加到 window.onload

window.onload = function(){
    // your code here
};

this will fire when all resources are loaded (which might be not what you want).

这将在加载所有资源时触发(这可能不是您想要的)。

Or put all of your code at the bottom the page (before the closing bodytag). The code will be run when the HTML is parsed.

或者将所有代码放在页面底部(在结束body标记之前)。代码将在解析 HTML 时运行。



FWIW, here is the jQuery code. You see, the use custom event handlers for IE and the other browsers, but use window.onloadas fallback:

FWIW,这是jQuery 代码。你看,为 IE 和其他浏览器使用自定义事件处理程序,但window.onload用作后备:

// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
    // Use the handy event callback
    document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

    // A fallback to window.onload, that will always work
    window.addEventListener( "load", jQuery.ready, false );

    // If IE event model is used
} else if ( document.attachEvent ) {
    // ensure firing before onload,
    // maybe late but safe also for iframes
    document.attachEvent("onreadystatechange", DOMContentLoaded);

    // A fallback to window.onload, that will always work
    window.attachEvent( "onload", jQuery.ready );

    // If IE and not a frame
    // continually check to see if the document is ready
    var toplevel = false;

    try {
        toplevel = window.frameElement == null;
    } catch(e) {}

    if ( document.documentElement.doScroll && toplevel ) {
        doScrollCheck();
    }
}

回答by JF Dion

If you plan on using a javascript library (like jQuery) I would rather go with the $(document).ready() statement which is called once the DOM is ready to be manipulated.

如果您打算使用 javascript 库(如 jQuery),我宁愿使用 $(document).ready() 语句,该语句在 DOM 准备好被操作时调用。

The other option I see would be to include your function call at the end of your HTML page so that all the HTML content would be loaded so you can afterward execute your code safely

我看到的另一个选项是在 HTML 页面的末尾包含您的函数调用,以便加载所有 HTML 内容,以便您之后可以安全地执行代码

回答by Olical

"The onload event waits for all binary content to download before firing. No kitty-tickilng until then."

“onload 事件在触发之前等待所有二进制内容下载。在那之前没有小猫tickilng。”

As this post says, it is called after all binary content is downloaded, you need to listen for a ready event either using jQuery's ready, or your own function. This project looks interesting.

正如这篇文章所说,在下载所有二进制内容后调用它,您需要使用 jQuery 的 ready 或您自己的函数来监听 ready 事件。这个项目看起来很有趣。

There are many cross browser implementations so use either jQuery or that project I linked to.

有许多跨浏览器实现,因此请使用 jQuery 或我链接到的那个项目。

I have written my own function for my library, it uses internal methods so will not work on its own but might give you a feel for what you have to do. You can find that function here.

我已经为我的库编写了自己的函数,它使用内部方法,因此不会单独工作,但可能会让您了解您必须做的事情。您可以在此处找到该功能。

回答by StuperUser

As with a lot of JavaScript this will depend on which browser you are using.

与许多 JavaScript 一样,这取决于您使用的浏览器。

As @Avitus' answer, have you looked at the execution point of JQuery's document ready event? This has been generalised across all browsers.

作为@Avitus 的回答,您是否查看过 JQuery 的文档就绪事件的执行点?这已在所有浏览器中推广。