【问题标题】:Is <body>.onLoad called before rendering is done?<body>.onLoad 是在渲染完成之前调用的吗?
【发布时间】:2013-02-10 07:23:14
【问题描述】:

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

为了澄清,我想在页面呈现在屏幕上之后运行一些 JS,所以真的是一个“post-everything 事件”。

【问题讨论】:

  • 如果您的页面完全呈现,然后您的 Javascript 操作 DOM,您将拥有未操作 DOM 的“闪现”,然后更改将显示出来。但是 onload 应该只在所有图像下载后调用,等等......
  • 所以....你想在 DOM 准备好或加载所有资源之后运行你的代码。抱歉,我不清楚。
  • 基本上看到前面的页面后,我就想运行一些代码。
  • @John "在渲染完成之前调用 onLoad 处理程序。"据我所知,在“onload”之后,您会发现布局已确定并且所有元素结构都已完成。什么经历让你不这么认为?其他信号是“ondomcontentloaded”和“onpageshow”。但是最大的跨浏览器兼容性会影响它们,因为许多浏览器的许多版本都不会触发它们(尤其是“onpageshow”,它通常仅限于“bfcache”功能)。 jQuery 泛化处理跨浏览器问题,但请注意它是“DOM Ready”,not 用于显示已完成。

标签: javascript html


【解决方案1】:

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

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

T1] "onLoad" 事件-- [无论您如何获得事件:addEventListener("Load"..., window.onload=..., etc.] 页面的所有部分都已被识别并下载 来自服务器并在本地系统的内存中。为了识别所有部分,已经进行了一些解析。(注意,“load”是“download”的同源词,而不是“parse”或“渲染”。)

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

T2] DOM-几乎-准备好了--这个 hack 非常简单并且完全跨浏览器。只需将您的 JS 放在 HTML 的最后,就在

【解决方案2】:

将回调附加到window.onload

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

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

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


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();
    }
}

【讨论】:

  • @StuperUser:不知道它是否在完全相同的点上引发(应该根据规范),但它是在 DOM 可用的点上引发的。
  • 我已经使用了onLoad,但它在我尝试的任何浏览器中都无法正常工作...当调用 JS 时,我的基本 HTML 可见,因为JS 正在做一些繁重的页面停顿。这可能是对 JS 的错误使用,但无论如何不应该在 方法触发之前渲染页面......这就是我所需要的。
  • @John:你试过在 HTML 页面底部添加代码吗?您确定您的代码设置正确吗?你能提供一个链接到你的页面吗?
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

      正如这篇文章所说,在下载所有二进制内容后调用它,您需要使用 jQuery 的 ready 或您自己的函数来侦听 ready 事件。 This project looks interesting.

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

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

      【讨论】:

        猜你喜欢
        • 2015-03-15
        • 2018-04-21
        • 1970-01-01
        • 2014-05-07
        • 1970-01-01
        • 2018-09-19
        • 1970-01-01
        • 2019-02-10
        • 1970-01-01
        相关资源
        最近更新 更多