javascript without $(document).ready沒有jQuery




jquery ready load (24)

這個跨瀏覽器的代碼將在DOM準備就緒後調用一個函數:

var domReady=function(func){
    var scriptText='('+func+')();';
    var scriptElement=document.createElement('script');
    scriptElement.innerText=scriptText;
    document.body.appendChild(scriptElement);
};

以下是它的工作原理:

  1. domReady的第一行調用函數的toString方法以獲取您傳入的函數的字符串表示形式,並將其包裝在立即調用該函數的表達式中。
  2. domReady的其餘部分用domReady創建一個腳本元素並將其附加到文檔的body
  3. DOM準備就緒後,瀏覽器將腳本標籤附加到body

例如,如果你這樣做: domReady(function(){alert();}); ,以下內容將附加到body元素:

 <script>(function (){alert();})();</script>

請注意,這僅適用於用戶定義的函數。 以下內容不起作用: domReady(alert);

我有一個使用$(document).ready的腳本,但它沒有使用jQuery中的其他任何東西。 我想通過刪除jQuery依賴項來減輕它的負擔。

如何在不使用jQuery的情況下實現自己的$(document).ready功能? 我知道使用window.onload不會是一樣的,因為window.onload會在加載所有圖像,框架等後觸發。


For IE9+:

function ready(fn) {
  if (document.readyState != 'loading'){
    fn();
  } else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}

function onDocReady(fn){
    (function c(){document.readyState!=="loading"?fn():setTimeout(c,9)})();
}   

function onDocLoad(fn){
    (function c(){document.readyState==="complete"?fn():setTimeout(c,30)})();
}    

onDocReady provides a callback when the HTML dom is ready to fully access/parse/manipulate.

onDocLoad provides a callback when everything has loaded (images etc)

  • These functions can be called whenever you want.
  • Supports multiple "listeners".
  • Will work in any browser.

編輯:

這是一個可行的替代jQuery的準備

function ready(callback){
    // in case the document is already rendered
    if (document.readyState!='loading') callback();
    // modern browsers
    else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
    // IE <= 8
    else document.attachEvent('onreadystatechange', function(){
        if (document.readyState=='complete') callback();
    });
}

ready(function(){
    // do something
});

採取從https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/

由於接受的答案還遠遠沒有完成,我將jQuery.ready()基於jQuery 1.6.2源代碼一起“準備好”了一個函數:

var ready = (function(){

    var readyList,
        DOMContentLoaded,
        class2type = {};
        class2type["[object Boolean]"] = "boolean";
        class2type["[object Number]"] = "number";
        class2type["[object String]"] = "string";
        class2type["[object Function]"] = "function";
        class2type["[object Array]"] = "array";
        class2type["[object Date]"] = "date";
        class2type["[object RegExp]"] = "regexp";
        class2type["[object Object]"] = "object";

    var ReadyObj = {
        // Is the DOM ready to be used? Set to true once it occurs.
        isReady: false,
        // A counter to track how many items to wait for before
        // the ready event fires. See #6781
        readyWait: 1,
        // Hold (or release) the ready event
        holdReady: function( hold ) {
            if ( hold ) {
                ReadyObj.readyWait++;
            } else {
                ReadyObj.ready( true );
            }
        },
        // Handle when the DOM is ready
        ready: function( wait ) {
            // Either a released hold or an DOMready/load event and not yet ready
            if ( (wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady) ) {
                // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
                if ( !document.body ) {
                    return setTimeout( ReadyObj.ready, 1 );
                }

                // Remember that the DOM is ready
                ReadyObj.isReady = true;
                // If a normal DOM Ready event fired, decrement, and wait if need be
                if ( wait !== true && --ReadyObj.readyWait > 0 ) {
                    return;
                }
                // If there are functions bound, to execute
                readyList.resolveWith( document, [ ReadyObj ] );

                // Trigger any bound ready events
                //if ( ReadyObj.fn.trigger ) {
                //    ReadyObj( document ).trigger( "ready" ).unbind( "ready" );
                //}
            }
        },
        bindReady: function() {
            if ( readyList ) {
                return;
            }
            readyList = ReadyObj._Deferred();

            // Catch cases where $(document).ready() is called after the
            // browser event has already occurred.
            if ( document.readyState === "complete" ) {
                // Handle it asynchronously to allow scripts the opportunity to delay ready
                return setTimeout( ReadyObj.ready, 1 );
            }

            // 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", ReadyObj.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", ReadyObj.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();
                }
            }
        },
        _Deferred: function() {
            var // callbacks list
                callbacks = [],
                // stored [ context , args ]
                fired,
                // to avoid firing when already doing so
                firing,
                // flag to know if the deferred has been cancelled
                cancelled,
                // the deferred itself
                deferred  = {

                    // done( f1, f2, ...)
                    done: function() {
                        if ( !cancelled ) {
                            var args = arguments,
                                i,
                                length,
                                elem,
                                type,
                                _fired;
                            if ( fired ) {
                                _fired = fired;
                                fired = 0;
                            }
                            for ( i = 0, length = args.length; i < length; i++ ) {
                                elem = args[ i ];
                                type = ReadyObj.type( elem );
                                if ( type === "array" ) {
                                    deferred.done.apply( deferred, elem );
                                } else if ( type === "function" ) {
                                    callbacks.push( elem );
                                }
                            }
                            if ( _fired ) {
                                deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
                            }
                        }
                        return this;
                    },

                    // resolve with given context and args
                    resolveWith: function( context, args ) {
                        if ( !cancelled && !fired && !firing ) {
                            // make sure args are available (#8421)
                            args = args || [];
                            firing = 1;
                            try {
                                while( callbacks[ 0 ] ) {
                                    callbacks.shift().apply( context, args );//shifts a callback, and applies it to document
                                }
                            }
                            finally {
                                fired = [ context, args ];
                                firing = 0;
                            }
                        }
                        return this;
                    },

                    // resolve with this as context and given arguments
                    resolve: function() {
                        deferred.resolveWith( this, arguments );
                        return this;
                    },

                    // Has this deferred been resolved?
                    isResolved: function() {
                        return !!( firing || fired );
                    },

                    // Cancel
                    cancel: function() {
                        cancelled = 1;
                        callbacks = [];
                        return this;
                    }
                };

            return deferred;
        },
        type: function( obj ) {
            return obj == null ?
                String( obj ) :
                class2type[ Object.prototype.toString.call(obj) ] || "object";
        }
    }
    // The DOM ready check for Internet Explorer
    function doScrollCheck() {
        if ( ReadyObj.isReady ) {
            return;
        }

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

        // and execute any waiting functions
        ReadyObj.ready();
    }
    // Cleanup functions for the document ready method
    if ( document.addEventListener ) {
        DOMContentLoaded = function() {
            document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
            ReadyObj.ready();
        };

    } else if ( document.attachEvent ) {
        DOMContentLoaded = function() {
            // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", DOMContentLoaded );
                ReadyObj.ready();
            }
        };
    }
    function ready( fn ) {
        // Attach the listeners
        ReadyObj.bindReady();

        var type = ReadyObj.type( fn );

        // Add the callback
        readyList.done( fn );//readyList is result of _Deferred()
    }
    return ready;
})();

如何使用:

<script>
    ready(function(){
        alert('It works!');
    });
    ready(function(){
        alert('Also works!');
    });
</script>

我不確定這個代碼是如何運作的,但它對我的表面測試很好。 這花了一段時間,所以我希望你和其他人能從中受益。

PS:我建議compiling它。

或者你可以使用http://dustindiaz.com/smallest-domready-ever

function r(f){/in/.test(document.readyState)?setTimeout(r,9,f):f()}
r(function(){/*code to run*/});

或者本地函數,如果你只需要支持新的瀏覽器(不像jQuery準備好,如果你在頁面加載後添加它,這將不會運行)

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})

只需將它添加到HTML頁面的底部即可

<script>
    Your_Function();
</script>

因為HTML文件是由上下分析的。


簡而言之,我們可以使用JavaScript方法代替jQuery中使用的$(document).ready()。

<script>
    document.addEventListener("DOMContentLoaded", function_name, false);
    function function_name(){
        statements;
    }
</script>

因此,當頁面準備就緒,即DOMContentLoaded時,函數function_name()將被調用。


這裡是測試DOM ready最小代碼片段,它可以在所有瀏覽器(甚至IE 8)上運行:

r(function(){
    alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}

看到這個answer


This was a good https://.com/a/11810957/185565 poor man's solution. One comment considered a counter to bail out in case of emergency. This is my modification.

function doTheMagic(counter) {
  alert("It worked on " + counter);
}

// wait for document ready then call handler function
var checkLoad = function(counter) {
  counter++;
  if (document.readyState != "complete" && counter<1000) {
    var fn = function() { checkLoad(counter); };
    setTimeout(fn,10);
  } else doTheMagic(counter);
};
checkLoad(0);

If you are loading jQuery near the bottom of BODY, but are having trouble with code that writes out jQuery(<func>) or jQuery(document).ready(<func>), check out jqShim on Github.

Rather than recreate its own document ready function, it simply holds onto the functions until jQuery is available then proceeds with jQuery as expected. The point of moving jQuery to the bottom of body is to speed up page load, and you can still accomplish it by inlining the jqShim.min.js in the head of your template.

I ended up writing this code to make moving all the scripts in WordPress to the footer, and just this shim code now sits directly in the header.


我只是使用:

setTimeout(function(){
    //reference/manipulate DOM here
});

而不像document.addEventListener("DOMContentLoaded" //etc就像在最頂級的答案中一樣,它的工作原理與IE9相反 - http://caniuse.com/#search=DOMContentLoaded只是最近才表示IE11。

例如,轉到https://netrenderer.com/index.php ,從下拉列表中選擇Internet Explorer 9,輸入https://dexygen.github.io/blog/oct-2017/jekyll/jekyll-categories/liquid-templates/2017/10/22/how-jekyll-builds-site-categories.html ,然後點擊“Render”,你會看到類似於這篇文章底部截圖的東西。

請參閱下面的JavaScript代碼,我在頭文件中操縱Jekyll“hacker”主題的樣式以符合我的喜好 - 特別是您可以引用if (location.pathname !== rootPath)塊來查看我如何插入HomeBlog Home鏈接,這些鏈接由IE9根據NetRenderer網站顯示。

有趣的是,我在2009年偶然發現了這個setTimeout解決方案: 是否正在檢查DOM矯枉過正的準備情況? ,這可能會稍微好一些,正如我的意思是使用各種框架的更複雜的方法。

setTimeout(function() {//delay execution until after dom is parsed
    var containerEls = document.getElementsByClassName('container');
    var headingEl = containerEls[0].getElementsByTagName('h1')[0];
    var headerEl = document.getElementsByTagName('header')[0];
    var downloadsSectionEl = document.getElementById('downloads');
    var rootPath = "/";
    var blogRootPath = "/blog/";

    containerEls[0].style.maxWidth = '800px';
    containerEls[1].style.maxWidth = '800px';
    headingEl.style.margin = '0';
    headerEl.style.marginBottom = '7px';
    downloadsSectionEl.style.margin = '0';

    if (location.pathname !== rootPath) {
        downloadsSectionEl.appendChild(generateNavLink('Home', rootPath));
        if (location.pathname !== blogRootPath) {
            downloadsSectionEl.appendChild(document.createTextNode(' | '));
            downloadsSectionEl.appendChild(generateNavLink('Blog Home', blogRootPath));
        }
    }

    function generateNavLink(linkText, hrefPath) {
        var navLink = document.createElement('a');
        var linkTextNode = document.createTextNode(linkText);
        navLink.setAttribute('href', hrefPath);
        navLink.appendChild(linkTextNode);
        return navLink;
    }
});


我最近使用這個移動網站。 這是John Resig從“Pro JavaScript技術”中的簡化版本。 這取決於addEvent。

var ready = ( function () {
  function ready( f ) {
    if( ready.done ) return f();

    if( ready.timer ) {
      ready.ready.push(f);
    } else {
      addEvent( window, "load", isDOMReady );
      ready.ready = [ f ];
      ready.timer = setInterval(isDOMReady, 13);
    }
  };

  function isDOMReady() {
    if( ready.done ) return false;

    if( document && document.getElementsByTagName && document.getElementById && document.body ) {
      clearInterval( ready.timer );
      ready.timer = null;
      for( var i = 0; i < ready.ready.length; i++ ) {
        ready.ready[i]();
      }
      ready.ready = null;
      ready.done = true;
    }
  }

  return ready;
})();

窮人的解決方案:

var checkLoad = function() {   
    document.readyState !== "complete" ? setTimeout(checkLoad, 11) : alert("loaded!");   
};  

checkLoad();  

查看小提琴

增加了這一點,我猜,更好一點,自己的範圍,和非遞歸

(function(){
    var tId = setInterval(function() {
        if (document.readyState == "complete") onComplete()
    }, 11);
    function onComplete(){
        clearInterval(tId);    
        alert("loaded!");    
    };
})()

查看小提琴


跨瀏覽器(舊瀏覽器)和一個簡單的解決方案:

var docLoaded = setInterval(function () {
    if(document.readyState !== "complete") return;
    clearInterval(docLoaded);

    /*
        Your code goes here i.e. init()
    */
}, 30);

在jsfiddle中顯示警報


值得一看的是Rock Solid addEvent()http://www.braksator.com/how-to-make-your-own-jquery

這是網站出現故障時的代碼

function addEvent(obj, type, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(type, fn, false);
        EventCache.add(obj, type, fn);
    }
    else if (obj.attachEvent) {
        obj["e"+type+fn] = fn;
        obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
        obj.attachEvent( "on"+type, obj[type+fn] );
        EventCache.add(obj, type, fn);
    }
    else {
        obj["on"+type] = obj["e"+type+fn];
    }
}

var EventCache = function(){
    var listEvents = [];
    return {
        listEvents : listEvents,
        add : function(node, sEventName, fHandler){
            listEvents.push(arguments);
        },
        flush : function(){
            var i, item;
            for(i = listEvents.length - 1; i >= 0; i = i - 1){
                item = listEvents[i];
                if(item[0].removeEventListener){
                    item[0].removeEventListener(item[1], item[2], item[3]);
                };
                if(item[1].substring(0, 2) != "on"){
                    item[1] = "on" + item[1];
                };
                if(item[0].detachEvent){
                    item[0].detachEvent(item[1], item[2]);
                };
                item[0][item[1]] = null;
            };
        }
    };
}();

// Usage
addEvent(window, 'unload', EventCache.flush);
addEvent(window, 'load', function(){alert("I'm ready");});

jQuery的答案對我來說非常有用。 有一點耐心,它滿足了我的需求。 我希望它能幫助其他人。

function onReady ( callback ){
    var addListener = document.addEventListener || document.attachEvent,
        removeListener =  document.removeEventListener || document.detachEvent
        eventName = document.addEventListener ? "DOMContentLoaded" : "onreadystatechange"

    addListener.call(document, eventName, function(){
        removeListener( eventName, arguments.callee, false )
        callback()
    }, false )
}

真的,如果你只關心Internet Explorer 9+ ,這段代碼就足以取代jQuery.ready

    document.addEventListener("DOMContentLoaded", callback);

如果您擔心Internet Explorer 6以及一些非常奇怪和罕見的瀏覽器,這將會起作用:

domReady: function (callback) {
    // Mozilla, Opera and WebKit
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", callback, false);
        // If Internet Explorer, the event model is used
    } else if (document.attachEvent) {
        document.attachEvent("onreadystatechange", function() {
            if (document.readyState === "complete" ) {
                callback();
            }
        });
        // A fallback to window.onload, that will always work
    } else {
        var oldOnload = window.onload;
        window.onload = function () {
            oldOnload && oldOnload();
            callback();
        }
    }
},


三種選擇:

  1. 如果script是主體的最後一個標記,那麼DOM將在執行腳本標記之前準備好
  2. 當DOM準備就緒時,“readyState”將變為“完成”
  3. 將所有內容放在'DOMContentLoaded'事件監聽器下

的onreadystatechange

  document.onreadystatechange = function () {
     if (document.readyState == "complete") {
     // document is ready. Do your stuff here
   }
 }

來源: MDN

DOMContentLoaded

document.addEventListener('DOMContentLoaded', function() {
   console.log('document is ready. I can sleep now');
});

關注石器時代瀏覽器:轉到jQuery源代碼並使用ready函數。 在這種情況下,你並沒有解析+執行你正在做的整個庫只是它的一小部分。


我們發現我們的一個快速和骯髒的跨瀏覽器實現,可以用最簡單的實現為絕大多數簡單的情況提供技巧:

window.onReady = function onReady(fn){
    document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};

Edit of the edit of @duskwuff to support Internet Explorer 8 too. The difference is a new call to the function test of the regex and the setTimeout with an anonymous function.

Also, I set the timeout to 99.

function ready(f){/in/.test(document.readyState)?setTimeout(function(){ready(f);},99):f();}

jQuery中的ready函數做了很多事情。 坦率地說,除非你的網站有非常小的輸出,否則我沒有看到取代它的意義。 jQuery是一個非常小的庫,它可以處理後面需要的各種跨瀏覽器的東西。

Anyway, there's little point in posting it here, just open up jQuery and look at the bindReady method.

It starts by calling either document.addEventListener("DOMContentLoaded") or document.attachEvent('onreadystatechange') depending on the event model, and goes on from there.


這個解決方案如何?

// other onload attached earlier
window.onload=function() {
   alert('test');
};

tmpPreviousFunction=window.onload ? window.onload : null;

// our onload function
window.onload=function() {
   alert('another message');

   // execute previous one
   if (tmpPreviousFunction) tmpPreviousFunction();
};

與jQuery相比,使用JavaScript等價物總是很好的。 一個原因是少了一個依賴的庫,它們比jQuery等效的要快得多。

jQuery等價物的一個奇妙參考是http://youmightnotneedjquery.com/

就你的問題而言,我從上面的鏈接中獲得了下面的代碼:)只有警告,它只適用於Internet Explorer 9+及更高版本。

function ready(fn) {
    if (document.readyState != 'loading') {
        fn();
    }
    else {
        document.addEventListener('DOMContentLoaded', fn);
    }
}

有一個基於標準的替代, DOMContentLoaded ,超過98%的瀏覽器支持 ,但不支持IE8:

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work
});

jQuery的本地函數比window.onload複雜得多,如下所示。

function bindReady(){
    if ( readyBound ) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", function(){
            document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
            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", function(){
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", arguments.callee );
                jQuery.ready();
            }
        });

        // If IE and not an iframe
        // continually check to see if the document is ready
        if ( document.documentElement.doScroll && window == window.top ) (function(){
            if ( jQuery.isReady ) return;

            try {
                // If IE is used, use the trick by Diego Perini
                // http://javascript.nwbox.com/IEContentLoaded/
                document.documentElement.doScroll("left");
            } catch( error ) {
                setTimeout( arguments.callee, 0 );
                return;
            }

            // and execute any waiting functions
            jQuery.ready();
        })();
    }

    // A fallback to window.onload, that will always work
    jQuery.event.add( window, "load", jQuery.ready );
}




jquery