【问题标题】:Why DOM ready event always runs after window.onload event with requirejs?为什么 DOM 就绪事件总是在带有 requirejs 的 window.onload 事件之后运行?
【发布时间】:2013-11-29 12:04:04
【问题描述】:

我在我的项目中使用 jquery 和 requirejs。最近,我发现了一些我没想到的东西。如果我通过 requirejs 加载 jquery 是什么。 DOM 就绪事件总是在 window.onload 事件之后触发。

这是我的例子:http://jsbin.com/ozusIBE/2

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>

  <img src="http://thejetlife.com/wp-content/uploads/2013/06/Times_Square_New_York_City_HDR.jpg" />

  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.5/require.min.js"></script>
  <script>

    window.onload = function () {
        console.log('window.onload');
    };
    $(function () {
            console.log('document.ready1');
    });

    requirejs.config({
        paths: { 
          jquery: ['//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min']
        }
    });

    require(['jquery'], function () {
        console.log('required moudels have been loaded');

        $(function () {
            console.log('document.ready2');
        });
    });

  </script>
</body>
</html>

当我加载没有缓存的页面时。控制台中的结果是:

document.ready1
required moudels have been loaded
window.onload
document.ready2

请注意,ready2 总是在 window.onload 之后运行。 如果我稍微更改一下代码,就会有所不同。

//do not use requirejs to load jquery
//require(['jquery'], function () {
require([], function () { 
    console.log('required moudels have been loaded');
    $(function () {
        console.log('document.ready2');
    });
});

结果是:

document.ready1
required moudels have been loaded
document.ready2
window.onload

似乎如果我使用 requrejs 将 jquery 作为 AMD 模块异步加载。 DOM 就绪事件是无用的。因为 DOM 就绪事件会在 window.onload 之后触发。

我不知道为什么会这样,有什么办法可以解决这个问题吗?



更新:
感谢德尔曼。 正如 dherman 提到的 document.readyState。我进行了小型调查并找到了解决该问题的方法。我已经在 Chrome 和 Firefox 上测试过了。它运作良好。但是,这可能不是一个完美的解决方案,因为所有版本的 IE 都可以在 DOM 完全加载之前具有交互状态。 (ref)

这是我的更新示例:http://jsbin.com/ozusIBE/16

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>

  <img src="http://upload.wikimedia.org/wikipedia/commons/a/ab/NYC_-_Time_Square_-_From_upperstairs.jpg" />

  <script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.9/require.min.js"></script>
  <script>

    requirejs.config({
        paths: { 
          jquery: ['//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min']
        }
    });

    require(['jquery'], function () {
      console.log('required moudels have been loaded');

      var init = function(){
        console.log('document.ready');
      };

      if ( document.attachEvent ? document.readyState === 'complete' : document.readyState !== 'loading' ){
        init();
      }else{
        $(function(){ init(); });
      }

    });


    window.onload = function () {
        console.log('window.onload');
    };


  </script>
</body>
</html>

【问题讨论】:

  • 我保证 dom 就绪事件在窗口加载之前触发。相反,绑定到它的代码是在窗口加载之后执行的,并且由于此时它已经准备好,它会立即执行。
  • 首先,在我的示例中,页面包含一张大图片,需要一段时间才能完全加载图片。其次,它在控制台中打印出句子 - “所需的模块已加载”并停止。过了一会儿,“window.onload”和“document.ready2”被打印出来了。并且“document.ready2”总是在“window.onload”之后打印。明显的 dom-ready-binding-function 在绑定到 dom-ready 时没有立即执行。
  • 你测试的是什么浏览器?有些浏览器实际上没有 dom 就绪事件,在这些浏览器中,jQuery 的 dom 就绪处理程序可能会以不同的方式触发。这种情况的处理方式已经从版本到版本(jQuery)发生了变化,我认为最近在 IE9/10 中正确触发但在 IE7/8 中较晚
  • 我在 chrome 中看到了这种行为:jsfiddle.net/SPHj8
  • 实际上...我的小提琴设置不正确,它包含两个版本的 jQuery。现在我没有看到您所描述的行为:jsfiddle.net/SPHj8/1 有时 onload 确实发生在 ready2 之前,但是,每次发生这种情况时,都是因为加载的 require 模块发生在 onload 之后,这意味着 domready 处理程序直到之后(一旦图像被缓存,这是预期的)

标签: jquery requirejs onload domready


【解决方案1】:

本机DOMContentLoaded 事件恰好在它应该触发的时候触发 - 当文档准备好时。由于您是通过 RequireJS 加载 jQuery,因此您可能会错过该事件。发生这种情况时,jQuery 不知道文档已准备好,必须等待 load 事件被触发,或者在 load 已经触发的情况下等待 document.readyState === "complete"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-16
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多