页面加载完成后执行javascript

Mat*_*vis 8 html javascript dom

我有一个html页面,其中包含一些预呈现的内容和一些未呈现的内容.我想立即显示预渲染的内容,然后开始渲染剩余的内容.我没有使用jQuery.

请参阅以下代码段.我曾经尝试这样做的各种方式,包括结束标记之前注入我的脚本,并提供我的脚本来填充DOM的回调window.onload,document.body.onloaddocument.addEventListener('DOMContentLoaded').在每种情况下,在呈现其余内容之前,页面不显示预呈现的内容.

<html><head></head>
  <body>
    <header>What it is, my doge?</header>
    <div id="main"></div>
    <script>
      var main = document.getElementById('main');
      for (var i = 0; i < 500; i++)
        main.innerText += new Date();
    </script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

<html><head></head>
  <body>
    <header>What it is, my doge?</header>
    <div id="main"></div>
    <script>
      var main = document.getElementById('main');
      document.body.onload = function() {
        for (var i = 0; i < 500; i++)
          main.innerText += new Date();
      };
    </script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

<html><head></head>
      <body>
        <header>What it is, my doge?</header>
        <div id="main"></div>
        <script>
          var main = document.getElementById('main');
          window.onload = function() {
            for (var i = 0; i < 500; i++)
              main.innerText += new Date();
          };
        </script>
      </body>
    </html>
Run Code Online (Sandbox Code Playgroud)

<html><head></head>
      <body>
        <header>What it is, my doge?</header>
        <div id="main"></div>
        <script>
          var main = document.getElementById('main');
          document.addEventListener('DOMContentLoaded', function() {
            for (var i = 0; i < 500; i++)
              main.innerText += new Date();
          });
        </script>
      </body>
    </html>
Run Code Online (Sandbox Code Playgroud)

一个有效的案例是window.setTimeout0超时.然而,这只是推迟了功能,直到没有什么可做的.这是最好的做法吗?

<html><head></head>
<body>
    <header>What it is, my doge?</header>
    <div id="main"></div>
    <script>
      var main = document.getElementById('main');
      window.setTimeout(function() {
        for (var i = 0; i < 500; i++)
          main.innerText += new Date();
      }, 0);
    </script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

svi*_*gen 11

最佳实践而言,没有一个.在良好,普遍可接受的实践方面,有一小部分.你打了一个:

setTimeout(function() { }, 1);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,在所有其他内联处理结束后,在浏览器的最小超时时间内执行该功能.

同样,如果要确保在某些条件为真后不久运行函数,请使用间隔:

var readyCheck = setInterval(function() {
  if (readyCondition) {
    /* do stuff */
    clearInterval(readyCheck);
  }
}, 1);
Run Code Online (Sandbox Code Playgroud)

在我自己的工作中,我一直在使用类似但更通用的解决方案.我在标题中定义了一个辅助函数:

var upon = function(test, fn) {
    if (typeof(test) == 'function' && test()) {
        fn();
    } else if (typeof(test) == 'string' && window[test]) {
        fn();
    } else {
        setTimeout(function() { upon(test, fn); }, 50);
    }
}; // upon()
Run Code Online (Sandbox Code Playgroud)

...并且在解析依赖项时触发其他功能:

upon(function() { return MyNS.Thingy; }, function() {
  //  stuff that depends on MyNS.Thingy
});

upon(function() { return document.readyState == 'complete';}, function() {
  // stuff that depends on a fully rendered document
});
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要更权威的良好做法,请关注Google的示例.创建一个外部async脚本并在第一个头之前注入它script:

var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true;
s.src = '/path/to/script.js';
var header_scripts = document.getElementsByTagName('script')[0];
header_scripts.parentNode.insertBefore(s, header_scripts);
Run Code Online (Sandbox Code Playgroud)

Google的解决方案理论上适用于所有浏览器(IE <10?),以便在不干扰文档加载的情况下尽快执行外部脚本.

如果您想要权威的常规做法,请查看jQuery onready解决方案的来源.