有没有一种正确的方法来处理带有require.js的DOM就绪事件? (不,domReady插件不起作用)

时间:2014-01-15 21:09:19

标签: javascript jquery dom requirejs

我已经阅读了很多关于此问题的Stack Exchange问​​题(我认为有几十个问题);不幸的是,它们要么是原始的,要么涵盖稍微不同的问题,要么格式错误,没有答案,要么回答不正确(尽管有些是被接受的)。我会尽量保持我的例子尽可能小以说明问题。

包含jQuery,大图像和DOM就绪事件处理程序

的页面

我们举一个最简单的例子:

<!DOCTYPE html>
<head>
    <script>
        var start = Date.now();
        function log(s) { console.log((Date.now()-start), s); }
        window.addEventListener('DOMContentLoaded', function() {log('Real DOMContentLoaded');});
    </script>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script>
        log('jQuery loaded');
        $(function() { log('jQuery DOM ready'); });
        $(window).load(function() { log('jQuery document loaded'); });
    </script>
</head>
<body>
    <img src="http://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png">
</body>

代码按预期工作,jQuery的DOM就绪事件提前触发:

288 "jQuery loaded"
307 "jQuery DOM ready"
314 "Real DOMContentLoaded"
1376 "jQuery document loaded"

与require.js相同

现在让我们使用require.js:

<!DOCTYPE html>
<head>
    <script>
        var start = Date.now();
        function log(s) { console.log((Date.now()-start), s); }
        window.addEventListener('DOMContentLoaded', function() {log('Real DOMContentLoaded');});
    </script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
    <script>
        require.config({
            paths: {
                jquery: "//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min"
            }
        });
        require(["jquery"], function($) {
            log('jQuery loaded');
            $(function() { log('jQuery DOM ready'); });
            $(window).load(function() { log('jQuery document loaded'); });
        });
    </script>
</head>
<body>
    <img src="http://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png">
</body>

突然之间,jQuery的DOM ready事件在文档完全加载之前不会触发:

297 "Real DOMContentLoaded"
607 "jQuery loaded"
1255 "jQuery DOM ready"
1258 "jQuery document loaded" 

显然,jQuery错过了浏览器的DOMContentLoaded事件,因此回退到window.onload来运行自己的ready事件。

与require.js domReady插件相同

现在让我们将require.js'es自己的domReady插件添加到混合:

<!DOCTYPE html>
<head>
    <script>
        var start = Date.now();
        function log(s) { console.log((Date.now()-start), s); }
        window.addEventListener('DOMContentLoaded', function() {log('Real DOMContentLoaded');});
    </script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
    <script>
        require.config({
            paths: {
                jquery: "//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min",
                domReady: "//cdnjs.cloudflare.com/ajax/libs/require-domReady/2.0.1/domReady"
            }
        });
        require(["domReady"], function(domReady) {
            log('domReady loaded');
            domReady(function() { log('domReady DOM ready'); });
        });
        require(["jquery"], function($) {
            log('jQuery loaded');
            $(function() { log('jQuery DOM ready'); });
            $(window).load(function() { log('jQuery document loaded'); });
        });
    </script>
</head>
<body>
    <img src="http://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png">
</body>

不幸的是,它与jQuery的ready事件没有任何不同:

341 "Real DOMContentLoaded"
582 "jQuery loaded"
648 "domReady loaded"
1284 "jQuery DOM ready"
1289 "jQuery document loaded"
1299 "domReady DOM ready" 

问题

是否有一个正确,漂亮,跨浏览器的方式来连接DOM ready ready处理程序与require.js和jQuery没有自定义hacks并重新发明轮子?如果它没有真正起作用的话,那么拥有require-domReady插件有什么意义呢?

1 个答案:

答案 0 :(得分:2)

我不会将此标记为&#34;已接受&#34;因为我并不为解决方案感到骄傲,但这是我最终得到的结果,记录(有人在评论中提问)。我将我的解决方案编码为我添加到jQuery的domReadyEx函数,以便在使用jQuery时随时可用:

<!DOCTYPE html>
<head>
    <script>
        var start = Date.now();
        function log(s) { console.log((Date.now()-start), s); }
        window.addEventListener('DOMContentLoaded', function() {log('Real DOMContentLoaded');});
    </script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
    <script>
        require.config({
            paths: {
                jquery: "//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min"
            }
        });
        require(["jquery"], function($) {
            log('jQuery loaded');
            $.domReadyEx = function(handler) {
                // Poor jQuery can't figure it itself if loaded asynchronously and falls back to window.onload which is undesirably late.
                if (document.readyState == 'interactive' || document.readyState == 'complete') {
                    handler();
                } else {
                    $(document).ready(handler);
                }
            }
            $(function() { log('jQuery DOM ready'); });
            $(window).load(function() { log('jQuery document loaded'); });
            $.domReadyEx(function() { log('jQuery.domReadyEx'); });
        });
    </script>
</head>
<body>
    <img src="http://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png">
</body>

输出:

417 "Real DOMContentLoaded"
516 "jQuery loaded"
517 "jQuery.domReadyEx"
1123 "jQuery DOM ready"
1128 "jQuery document loaded"

我非常确定它不是完全跨浏览器的,但我并不关心旧版浏览器或IE中代码运行速度慢的问题。