【问题标题】:$(document).ready() source$(document).ready() 源
【发布时间】:2011-03-26 17:15:28
【问题描述】:

我需要等待我的 JavaScript 中的文档准备就绪,以便在正文底部插入一个 div。

我想:

  • 使这个 JavaScript 文件尽可能小(如果可能,将其编译到
  • 在闭包中内联提供文档就绪性的代码(不导出它)

在我的文件中内联整个 jQuery 源会太大,所以我正在寻找其他方法。 window.onload 可以,但我特别希望文档准备就绪,而不是等待 window.onload 事件。

有谁知道可以做到这一点的 JS sn-p 吗?还是我应该只复制 jQuery 的部分源代码?

编辑:

我设法爬取了 jQuery 源代码并与以下 sn-p 放在一起:

var ready = (function () {
    var ready_event_fired = false;
    var ready_event_listener = function (fn) {

        // Create an idempotent version of the 'fn' function
        var idempotent_fn = function () {
            if (ready_event_fired) {
                return;
            }
            ready_event_fired = true;
            return fn();
        }

        // The DOM ready check for Internet Explorer
        var do_scroll_check = function () {
            if (ready_event_fired) {
                return;
            }

            // If IE is used, use the trick by Diego Perini
            // http://javascript.nwbox.com/IEContentLoaded/
            try {
                document.documentElement.doScroll('left');
            } catch(e) {
                setTimeout(do_scroll_check, 1);
                return;
            }

            // Execute any waiting functions
            return idempotent_fn();
        }

        // If the browser ready event has already occured
        if (document.readyState === "complete") {
            return idempotent_fn()
        }

        // Mozilla, Opera and webkit nightlies currently support this event
        if (document.addEventListener) {

            // Use the handy event callback
            document.addEventListener("DOMContentLoaded", idempotent_fn, false);

            // A fallback to window.onload, that will always work
            window.addEventListener("load", idempotent_fn, 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", idempotent_fn);

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

            // 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) {
                return do_scroll_check();
            }
        }
    };
    return ready_event_listener;
})();

// TEST
var ready_1 = function () {
    alert("ready 1");
};
var ready_2 = function () {
    alert("ready 2");
};
ready(function () {
    ready_1();
    ready_2();
});

非常感谢您帮助我在 jQuery 源代码中找到它。我现在可以将所有这些放在一个闭包中并完成我的工作,而无需导出任何函数并污染全局范围。

【问题讨论】:

  • 您可以从 Google 的服务器获取 jQuery 源代码,这样您就可以很好地更改它已经被缓存了。

标签: javascript jquery


【解决方案1】:

一种选择是从 github 获取 core.js jQuery 文件。

对于不需要的代码,您可能可以将其精简很多。然后通过 YUI 压缩器运行它,它应该很小。

我试过了,这段代码运行正常:

$(function() {
    var newDiv = document.createElement('div');
    document.getElementsByTagName('body')[0].appendChild(newDiv);
});

更新:这是我得到的一样小。它完全来自jQuery,大约 1,278 字节(压缩)。 gzip 时应该会变小。

唯一的区别是你需要这样称呼它:

$.fn.ready(function() {
    // your code
});

YUI 压缩:

(function(){var e=function(i,j){},c=window.jQuery,h=window.$,d,g=false,f=[],b;e.fn={ready:function(i){e.bindReady();if(e.isReady){i.call(document,e)}else{if(f){f.push(i)}}return this}};e.isReady=false;e.ready=function(){if(!e.isReady){if(!document.body){return setTimeout(e.ready,13)}e.isReady=true;if(f){var k,j=0;while((k=f[j++])){k.call(document,e)}f=null}if(e.fn.triggerHandler){e(document).triggerHandler("ready")}}};e.bindReady=function(){if(g){return}g=true;if(document.readyState==="complete"){return e.ready()}if(document.addEventListener){document.addEventListener("DOMContentLoaded",b,false);window.addEventListener("load",e.ready,false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",b);window.attachEvent("onload",e.ready);var i=false;try{i=window.frameElement==null}catch(j){}if(document.documentElement.doScroll&&i){a()}}}};d=e(document);if(document.addEventListener){b=function(){document.removeEventListener("DOMContentLoaded",b,false);e.ready()}}else{if(document.attachEvent){b=function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",b);e.ready()}}}}function a(){if(e.isReady){return}try{document.documentElement.doScroll("left")}catch(i){setTimeout(a,1);return}e.ready()}window.jQuery=window.$=e})();

完整源代码(同样,这是jQuery 代码):

(function() {
var jQuery = function( selector, context ) {
    },
    _jQuery = window.jQuery,
    _$ = window.$,

    rootjQuery,
    readyBound = false,
    readyList = [],
    DOMContentLoaded;

jQuery.fn = {
    ready: function( fn ) {
        jQuery.bindReady();
        if ( jQuery.isReady ) {
            fn.call( document, jQuery );
        } else if ( readyList ) {
            readyList.push( fn );
        }
        return this;
    }
};
jQuery.isReady = false;
jQuery.ready = function() {
        if ( !jQuery.isReady ) {
            if ( !document.body ) {
                return setTimeout( jQuery.ready, 13 );
            }
            jQuery.isReady = true;
            if ( readyList ) {
                var fn, i = 0;
                while ( (fn = readyList[ i++ ]) ) {
                    fn.call( document, jQuery );
                }
                readyList = null;
            }
            if ( jQuery.fn.triggerHandler ) {
                jQuery( document ).triggerHandler( "ready" );
            }
        }
    };
jQuery.bindReady = function() {
        if ( readyBound ) {
            return;
        }
        readyBound = true;

        if ( document.readyState === "complete" ) {
            return jQuery.ready();
        }
        if ( document.addEventListener ) {
            document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
            window.addEventListener( "load", jQuery.ready, false );
        } else if ( document.attachEvent ) {

            document.attachEvent("onreadystatechange", DOMContentLoaded);
            window.attachEvent( "onload", jQuery.ready );

            var toplevel = false;
            try {
                toplevel = window.frameElement == null;
            } catch(e) {}
            if ( document.documentElement.doScroll && toplevel ) {
                doScrollCheck();
            }
        }
    };
rootjQuery = jQuery(document);
if ( document.addEventListener ) {
    DOMContentLoaded = function() {
        document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
        jQuery.ready();
    };
} else if ( document.attachEvent ) {
    DOMContentLoaded = function() {
        if ( document.readyState === "complete" ) {
            document.detachEvent( "onreadystatechange", DOMContentLoaded );
            jQuery.ready();
        }
    };
}
function doScrollCheck() {
    if ( jQuery.isReady ) {
        return;
    }
    try {

        document.documentElement.doScroll("left");
    } catch(e) {
        setTimeout( doScrollCheck, 1 );
        return;
    }
    jQuery.ready();
}
window.jQuery = window.$ = jQuery;
})();

我确定还有更多字节可以删除。

别忘了:

/*!
 * jQuery JavaScript Library v1.4.2
 * http://jquery.com/
 *
 * Copyright 2010, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
*/

【讨论】:

  • 感谢您指出这段棘手的代码!我更改了代码,因此它不会导出任何全局变量,但功能是相同的。
  • @Attila - 不客气。唯一的全局变量应该是$jQuery。当然摆脱$ 是个好主意。此外,还应包括正确的版权信息。
  • 啊,感谢您提醒我包含正确的版权信息。我对此不以为然,因为所有实际代码最初都来自 jQuery,我只是重命名了一些函数以符合我的口味:)
  • 所以,这里的含义是,如果我将 2.0.3 JQuery core.js 注入到我的网站测试中,我将可以访问它的“就绪”功能,并且只需注入它,它就会禁用旧式“DOMContentLoaded”监听器?
【解决方案2】:

您可以从脚本开始:http://snipplr.com/view/6029/domreadyjs/,但未针对最新的 Safari 进行优化(但可以工作)(例如,使用计时器而不是支持的 DOMContentLoaded)。

【讨论】:

    【解决方案3】:

    several implementations for "DOMReady" 函数,但我能找到的大多数似乎有点过时,所以我不知道它们在 IE8 等下的表现如何。

    我建议使用 jQuery 的 ready(),因为我认为它可以保证最大的跨浏览器兼容性。我不是 jQuery 源代码方面的专家,但 this 似乎是正确的位置(第 812-845 行或搜索 function bindReady)。

    【讨论】:

      猜你喜欢
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      • 2011-04-11
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多