$ (belge). jQuery olmadan zaten eşdeğer


2017

Kullanan bir komut dosyası var $(document).ready, ama jQuery başka bir şey kullanmaz. JQuery bağımlılığını kaldırarak hafifletmek istiyorum.

$(document).readyJQuery kullanmadan kendi işlevlerimi nasıl uygulayabilirim ? Tüm resimler, çerçeveler vb. Yüklendikten sonra kullanımın yangınlarla window.onloadaynı olmayacağını biliyorum window.onload.


296
... ve kesinlikle aynı işlevsellik değil.
Joel Mueller

40
As Bu cevap size jQuery gelen bütün istediğim eğer devletler, $(document).readysayfanın yerine üst kısmında çok alt adresinden kodu çalıştırarak kolayca bu sorunu çözebilir. HTML5Boilerplate bu yaklaşımı kullanır.
Blazemonger

3

Çağrımı belgenin sonunda verdim ve bu da sorunumu çözdü. İşlev çağrıldığında her şey yüklenir.
IgniteCoders

Yanıtlar:


1440

IE8 olmasa da tarayıcıların% 98'inden fazlasıDOMContentLoaded tarafından desteklenen standartlara dayalı bir değiştirme var :

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

jQuery'nin yerel işlevi, aşağıda gösterildiği gibi, sadece window.onload'dan çok daha karmaşıktır.

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 );
}

19
Birisi sadece düşebilir kod istiyorsa burada gerçek bir çalışma sade javascript uygulaması: stackoverflow.com/questions/9899372/…
jfriend00 13:14

4
jQuery DOM hazır kodu basitleştirilmiş gibi görünüyor: github.com/jquery/jquery/blob/master/src/core/ready.js
Jose Nobile

2
@JoseNobile çünkü eski tarayıcı desteğini
düşürdüler

16
Sanırım hepimiz IE8'den devam etmeye hazırız ...;). Bağlantı için teşekkürler, @JoseNobile.
Con Antonakos

13
Daha sonra komut dosyası yüklenirse DOMContentLoaded çalışmaz. JQuery belge hazır her zaman yürütür.
Jared Insel

343

Düzenle:

İşte jQuery için uygun bir yedek

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
});

Alındığı https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/

Https://stackoverflow.com/a/9899701/175071 adresinden alınan bir başka iyi domReady işlevi


Kabul edilen cevap tamamlanmaktan çok uzak olduğundan jQuery.ready(), jQuery 1.6.2 kaynağına dayalı gibi bir "hazır" işlevi birleştirdim :

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;
})();

Nasıl kullanılır:

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

Bu kodun ne kadar işlevsel olduğundan emin değilim, ancak yüzeysel testlerimle iyi çalıştı. Bu biraz zaman aldı, umarım siz ve başkaları bundan faydalanabilir.

PS .: Derlemenizi öneririm .

Veya http://dustindiaz.com/smallest-domready-ever adresini kullanabilirsiniz :

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

veya yerel işlevi yalnızca yeni tarayıcıları desteklemeniz gerekiyorsa (jQuery için hazır değilse, sayfa yüklendikten sonra bunu eklerseniz bu çalışmaz)

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

14
@TimoHuovinen Alternatifleri: Zepto.js (9.1 kb), Snack.js (8.1 kb), $ dom (2.3 kb) ve 140 Medley (0.5 kb). Düzenleme: Ender'e de göz atabilirsiniz.
Frederik Krautwald

2
@FrederikKrautwald $ dom istediğim gibi geliyor, ancak faturaya uyup uymadığından emin değilim. Zepto da gerçekten umut verici görünüyor, paylaştığın için teşekkürler!
Timo Huovinen

@TimoHuovinen Ender'e bakmadıysanız kesinlikle bir göz atmalısınız, enderjs.com .
Frederik Krautwald

2
@Timo Huovinen: Sorunuz gerçekten çok geniş! JQuery oluşturulduğunda, günümüzde daha az önemli olan tarayıcılar tarafından üretilen birçok çapraz tarayıcı sorunu ortaya koydu. Bugün "sadece javascript" olduğundan daha kolay. Şu anda, "tümünü içeren büyük bir 20kb sıkıştırılmış" oluşturmak kesinlikle hepsini listelememeyi tercih ettiğim pek çok nedenden dolayı iyi bir fikirdi.
dotpush

1
Bunu sevmedim. İnsanlar bu yanıtı tercih ederse, neden jQuery'yi en başta bırakmak istediğinizi kendinize sorun. Tüm bu tarayıcı geri dönüşü şişesiyle paketinize tam olarak aynı işlevselliği elde edecekseniz, biraz anlamsız. İlk etapta jQuery'den kaçınmanın asıl amacı bu değil mi?
Phil

208

Üç seçenek:

  1. Eğer scriptvücudun son etikettir, DOM komut dosyası etiketi çalışmasından önce hazır olacağını
  2. DOM hazır olduğunda "readyState", "tamamlandı" olarak değişir
  3. Her şeyi 'DOMContentLoaded' olay dinleyicisine yerleştirin

onreadystatechange

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

Kaynak: MDN

DOMContentLoaded

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

Taş Devri Tarayıcıları Hakkında Endişeli: jQuery kaynak koduna gidin vereadyişlevikullanın. Bu durumda tüm kütüphaneyi ayrıştırmıyorsunuz + yürütmüyorsunuz, kütüphanenin sadece çok küçük bir kısmını yapıyorsunuz.


3
Bu ikinci örnek işaretli cevaplardan çok daha zarif ve özlüdür. Bu neden doğru olan olarak işaretlenmedi?
0112

2
DOMContentLoaded için hala +1, tam olarak istediğimi yaptı.
tripleee

1
onreadystatechange benim için hile yaptı ... zaman uyumsuz jquery yükleme sonra bazı komut dosyası çalıştırmak gerekiyordu.
Abram

2
Tıpkı bir FYI gibi, # 1 tamamen doğru değildir. DOM bitmeden sayfanın sonundaki bir komut dosyasının yüklenmesi oldukça olasıdır. Bu yüzden dinleyiciler daha üstündür. Tarayıcı bittiğinde dinlerler. Sonuna koymak, komut dosyası yükünün tarayıcının oluşturabileceğinden daha yavaş olduğunu parmaklarınızı geçiyor.
Machavity

1
bu varyant, doküman yüklemeyi bitirdiğinde de çalışır, lütfen (imo best) yanıtınızı güncelleyebiliyorsanız güncelleyin: if (document.readyState == 'complete') {init (); } else {document.onreadystatechange = function () {if (document.readyState == 'tamamlandı') {init (); }}}
ZPiDER

87

Senin yerleştirin <script>/*JavaScript code*/</script>hakkı kapanış önce </body> etiketi.

Kuşkusuz, bu herkesin amaçlarına uygun olmayabilir, çünkü sadece JavaScript dosyasında bir şey yapmak yerine HTML dosyasını değiştirmeyi gerektirir document.ready, ancak yine de ...


Bana öyle geliyor ki, sayfa henüz hazır olmadığından, şu veya bu tarayıcılarda bunu yapamazsınız gibi uyumluluk sorunları vardı. Ne yazık ki daha net hatırlayamıyorum. Bununla birlikte, tüm vakaların% 99'unda yeterince yakın bir yol için +1 (ve Yahoo! tarafından önerilmektedir).
Boldewyn

7
Aslında sayfanın altına bir komut dosyası koymak neredeyse mükemmel bir çözümdür. Çapraz tarayıcı çalışır ve belgeyi simüle eder. Zaten mükemmel. Tek dezavantajı, bazı akıllı kod kullanmaktan (biraz) daha rahatsız edici olmasıdır, oluşturduğunuz komut dosyasının kullanıcısından hazır veya init işlevinizi çağırmak için ekstra bir komut dosyası parçası eklemesini istemeniz gerekir.
Stijn de Witt

@StijndeWitt - Bir init işlevini çağırmak zorunda kalmanızın anlamı nedir? Document.ready kullanan bir komut dosyası, onu çağırmak için başka bir istemci koduna ihtiyaç duymaz, kendi kendine yetir ve kodun gövdenin sonunda yer aldığı kodun karşılığı da bağımsız olabilir ve başka bir kod da çağırmanız gerekir.
nnnnnn

1
Komut dosyasını neden kapanış gövdesi etiketinden sonra ve kapanış etiketinden önce </html>koymuyorsunuz?
Charles Holbrow

1
@CharlesHolbrow Tüm tarayıcılar doğru şekilde yorumlasa da, geçerli html olmasını istiyorsanız, htmletiket yalnızca headve içermelidir body.
Alvaro Montoro

66

Zavallı adamın çözümü:

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

checkLoad();  

Kemanı Görüntüle

Bunu ekledim, sanırım biraz daha iyi, kendi kapsamı ve özyinelemesiz

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

Kemanı Görüntüle


8
@PhilipLangford Ya da sadece a'nın içine koyun setIntervalve özyinelemeyi tamamen kaldırın.
Alex W

1
@Raveren, hmm haklısın, yayınladığımda test ettiğimden eminim. her neyse, daha da basitleşti, şimdi fonksiyon çağrıldı, sarma yok.
Jakob Sternberg

24
Bu seksi değil. Hayır. Bir şeyleri tespit etmek için zamanlayıcıları / aralıkları kullanmak "işe yarayabilir" ama bu şekilde programlamaya devam ederseniz, tuzuna değecek daha büyük bir proje burun dalışı yapacaktır. Birlikte böyle şeyleri hackleme. Doğru yap. Lütfen. Bu tür bir kod geliştirme ekosistemini incitir çünkü daha iyi bir çözüm vardır ve bunu BİLİRSİNİZ.
dudewad

1
Bu cevap çok daha yakın düşünüyorum dustindiaz.com/smallest-domready-ever : Böylece I komut geliştirilmiş jsfiddle.net/iegik/PT7x9
iegik

1
@ReidBlomquist Evet, ve bu "yanlış" bir yol, ve ben bunu işaret ediyorum (biraz da olsa, biliyorum). Bunu yanlış yaparak bir şekilde ekosisteme "yardım etmek" olduğunu söyleyebilirsiniz, ama sorun şu ki, insanların daha iyi tanıma deneyimine sahip olmadıkları için "iyi" kod için aldıkları kötü kod miktarı ile ekosisteme yardım ETMEZ, çünkü o zaman bu kötü kodu alacak ve gerçek bir üretim mimari çözümüne uygulayacaklardır. Yani, sanırım, sadece bu "yanlışlık" konusundaki görüşümüzün farklı olması gerekecek.
dudewad

34

Bunu kullanıyorum:

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

Not: Bu, muhtemelen yalnızca daha yeni tarayıcılarla çalışır, özellikle de bunlar: http://caniuse.com/#feat=domcontentloaded


13
IE9 ve üstü aslında
Pascalius

Bu, document_start veya document_idle etkinliğini bağladıysanız Chrome Uzantısı içerik komut dosyalarında da harika çalışır.
Volomike

21

Gerçekten, yalnızca Internet Explorer 9+ ile ilgileniyorsanız , bu kodun değiştirilmesi yeterli olacaktır jQuery.ready:

    document.addEventListener("DOMContentLoaded", callback);

Internet Explorer 6 ve bazı gerçekten garip ve nadir tarayıcılar hakkında endişeleniyorsanız , bu işe yarayacaktır:

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();
        }
    }
},

18

Bu soru oldukça uzun zaman önce soruldu. Bu soruyu yeni gören herkes için, artık "jquery'ye ihtiyacınız olmayabilir" adlı bir site var - gerekli IE desteği seviyesine göre - jquery tüm işlevselliği ve bazı alternatif, daha küçük kütüphaneler sağlar.

IE8 belgesi hazır komut dosyası size göre jquery gerekmeyebilir

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

Acaba bunun neden 'onreadystatechange'gerekli olduğunu merak ediyorumdocument.attachEvent('onload', fn);
Luke

13

Son zamanlarda bunu bir mobil site için kullanıyordum. Bu, John Resig'in "Pro JavaScript Teknikleri" nden basitleştirilmiş sürümüdür. AddEvent'e bağlıdır.

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;
})();

13
Bu koda dikkat edin. $ (Document) .ready ile eşdeğer DEĞİLDİR. Bu kod, document.body hazır olduğunda DOM'un tamamen yüklendiğini garanti etmeyen geri aramayı tetikler.
Karolis

12

Çapraz tarayıcı (eski tarayıcılar da) ve basit bir çözüm:

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

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

Jsfiddle'da uyarı gösteriliyor


DOM'nin yüklenmesi 30ms'den fazla sürmesi dışında, kod çalışmaz.
Quelklef

1
@Quelklef that setInterval not setTimeout
Pawel

11

JQuery yanıtı benim için oldukça faydalı oldu. Biraz refactory ile benim ihtiyaçlarını iyi monte. Umarım herkese yardımcı olur.

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 )
}

bazı tarayıcılarda, removeListeneriçerik olarak belge ile çağrılması gerekir; removeListener.call(document, ...
Ron

9

Tüm tarayıcılarda (hatta IE 8'de) çalışan DOM'u test etmek için en küçük kod snippet'i :

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

Bu cevaba bakınız .


6

Bunu HTML sayfanızın altına ekleyin ...

<script>
    Your_Function();
</script>

Çünkü, HTML dokümanları üst-alt tarafından ayrıştırılır.


7
Bu kod yürütüldüğünde DOM'un oluşturulduğunu nasıl anlarsınız? Yüklü ve ayrıştırılmış CSS dahil mi? DOMContentLoaded tarayıcı API'sı bunun için tasarlanmıştır.
Dan

Gerçekten js ile ne yapmak istediğine bağlı. Sayfa bittiğinde veya bitmediğinde gerçekten bir şey yürütmesi gerekiyorsa.
davefrassoni

5

Bakmaya değer Rock Solid addEvent () ve http://www.braksator.com/how-to-make-your-own-jquery 'e .

İşte site kapanması durumunda kod

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");});

İkinci bağlantı koptu.
Peter Mortensen


4

Bu tarayıcılar arası kod, DOM hazır olduğunda bir işlevi çağırır:

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

Şöyle çalışır:

  1. İlk satır, domReadyilettiğiniz toStringişlevin dize ile temsilini almak için işlevin yöntemini çağırır ve hemen işlevi çağıran bir ifadeye sarar.
  2. Geri kalanı domReadyifadeyle birlikte bir komut dosyası öğesi oluşturur ve bunubody belgenin .
  3. Tarayıcı body, DOM hazır olduktan sonra eklenen komut dosyası etiketlerini çalıştırır .

Örneğin, bunu yaparsanız: öğeye domReady(function(){alert();});aşağıdakiler eklenir body:

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

Bunun yalnızca kullanıcı tanımlı işlevler için çalıştığını unutmayın. Aşağıdakiler işe yaramaz:domReady(alert);


3

Bu çözüme ne dersiniz?

// 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();
};

3
"Load" ile pencerede addEventListener kullanabilirsiniz. Dinleyiciler art arda yürütülür ve manuel olarak zincirlemeye gerek yoktur.
Zaffy

1
Ancak yük hazırdan farklıdır. 'Yükleme', belge 'hazır' olmadan önce bile gerçekleşir. Hazır bir belgede DOM yüklü, yüklü pencerede mutlaka DOM hazır olmaz. Yine de iyi cevap
Mzn

1
@Mzn: Bence bu geriye doğru. Bence belge hazır pencere yükleme olayından önce olur . "Genel olarak, tüm görüntülerin tam olarak yüklenmesini beklemek gerekmez. Kod daha önce yürütülebilirse, genellikle .ready () yöntemine gönderilen bir işleyiciye yerleştirmek en iyisidir." ( api.jquery.com/load-event )
Tyler Rick

bu, sayfadaki window.onload olaylarının geri kalanını geçersiz kılar ve sorunlara neden olur. mevcut olanın üstüne etkinlik eklemelidir.
Teoman shipahi

Yükleme olayı çok geç olabilir. Üçüncü taraf harici js / görüntülere bağlıyken kullanmak acı vericidir ... Kontrol etmediğiniz, yanıt vermeyen ve her şey başarısız olan bir sunucu. DOMContentLoaded kullanmak sadece bir optimizasyon değil, aynı zamanda daha güvenlidir!
dotpush

3

JQuery ile karşılaştırıldığında JavaScript eşdeğerlerini kullanmak her zaman iyidir. Bunun bir nedeni, bağımlı olması gereken bir kütüphane daha azdır ve jQuery eşdeğerlerinden çok daha hızlıdır.

JQuery eşdeğerleri için harika bir referans http://youmightnotneedjquery.com/ .

Sorunuza gelince, yukarıdaki bağlantıdan aşağıdaki kodu aldım :) Sadece uyarı sadece Internet Explorer 9 ve üstü ile çalışır .

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

3

En az ve% 100 çalışma

Cevabı PlainJS'den aldım ve benim için iyi çalışıyor. DOMContentLoadedTüm tarayıcılarda kabul edilebilecek şekilde genişletilir .


Bu işlev jQuery'nin $(document).ready()yöntemine eşdeğerdir :

document.addEventListener('DOMContentLoaded', function(){
    // do something
});

Bununla birlikte, jQuery'den farklı olarak, bu kod yalnızca modern tarayıcılarda (IE> 8) düzgün bir şekilde çalışır ve belgenin bu komut dosyasının eklendiği anda (örn. Ajax aracılığıyla) oluşturulmuş olması durumunda olmaz. Bu nedenle, bunu biraz genişletmeliyiz:

function run() {
    // do something
}

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

Bu temelde tüm olasılıkları kapsar ve jQuery yardımcısının yerini alabilir.



2

Minimal bir uygulama ile en basit vakalar için hile yapabilen hızlı ve kirli bir çapraz tarayıcı uygulaması bulduk:

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

nedir doc.body?
Nabi KAZ

2

Burada sunulan setTimeout / setInterval çözümleri yalnızca belirli durumlarda çalışır.

Sorun özellikle 8'e kadar olan eski Internet Explorer sürümlerinde ortaya çıkıyor.

Bu setTimeout / setInterval çözümlerinin başarısını etkileyen değişkenler şunlardır:

1) dynamic or static HTML
2) cached or non cached requests
3) size of the complete HTML document
4) chunked or non chunked transfer encoding

bu sorunu çözen orijinal (yerel Javascript) kodu burada:

https://github.com/dperini/ContentLoaded
http://javascript.nwbox.com/ContentLoaded (test)

bu, jQuery ekibinin uygulamalarını oluşturduğu koddur.


1

İşte kullandığım, hızlı ve bence tüm üsleri kapsıyor; IE <9 hariç her şey için çalışır.

(() => { function fn() {
    // "On document ready" commands:
    console.log(document.readyState);
};  
  if (document.readyState != 'loading') {fn()}
  else {document.addEventListener('DOMContentLoaded', fn)}
})();

Bu tüm vakaları yakalar gibi görünüyor:

  • DOM zaten hazırsa hemen tetiklenir (DOM "yükleniyor" değilse, "etkileşimli" veya "tamamlandı" ise)
  • DOM hala yükleniyorsa, DOM kullanılabilir olduğunda (etkileşimli) bir olay dinleyicisi ayarlar.

DOMContentLoaded olay IE9 ve diğer her şey mevcuttur, bu yüzden kişisel olarak bunu kullanmak için sorun olduğunu düşünüyorum. Kodunuzu ES2015'ten ES5'e aktarmıyorsanız, ok işlevi bildirimini normal bir anonim işleve yeniden yazın.

Tüm varlıklar yüklenene kadar beklemek isterseniz, görüntülenen tüm görüntüler vb. Bunun yerine window.onload öğesini kullanın.


1

Çok eski tarayıcıları desteklemeniz gerekmiyorsa, harici komut dosyanız async özniteliği yüklü olsa bile bunu yapmanın bir yolu :

HTMLDocument.prototype.ready = new Promise(function(resolve) {
   if(document.readyState != "loading")
      resolve();
   else
      document.addEventListener("DOMContentLoaded", function() {
         resolve();
      });
});

document.ready.then(function() {
   console.log("document.ready");
});

0

IE9 + için:

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

0

BODY'nin altına yakın bir yerde jQuery yüklüyorsanız, ancak jQuery (<func>) veya jQuery (belge) .ready (<func>) yazan kodla ilgili sorun yaşıyorsanız, Github'da jqShim'i kontrol edin .

Kendi belgeye hazır işlevini yeniden oluşturmak yerine, jQuery kullanılabilir hale gelene kadar işlevleri bekler ve beklendiği gibi jQuery ile devam eder. JQuery'yi gövdenin altına taşımanın amacı, sayfa yükünü hızlandırmaktır ve yine de şablonunuzun başındaki jqShim.min.js dosyasını satırlayarak başarabilirsiniz.

WordPress'teki tüm komut dosyalarını altbilgiye taşımak için bu kodu yazdım ve sadece bu şim kodu şimdi doğrudan başlıkta oturuyor.


0

Bunu dene:

function ready(callback){
    if(typeof callback === "function"){
        document.addEventListener("DOMContentLoaded", callback);
        window.addEventListener("load", callback);
    }else{
        throw new Error("Sorry, I can not run this!");
    }
}
ready(function(){
    console.log("It worked!");
});

Lol geri aramayı iki kez yapacaksın
Andrew

0
function onDocReady(fn){ 
    $d.readyState!=="loading" ? fn():document.addEventListener('DOMContentLoaded',fn);
}

function onWinLoad(fn){
    $d.readyState==="complete") ? fn(): window.addEventListener('load',fn);
} 

onDocReady , HTML tam olarak erişmeye / ayrıştırmaya / değiştirmeye hazır olduğunda geri arama sağlar.

onWinLoad her şey yüklendiğinde geri arama sağlar (resimler vb.)

  • Bu işlevler istediğiniz zaman çağrılabilir.
  • Birden fazla "dinleyici" destekler.
  • Herhangi bir tarayıcıda çalışır.

0
(function(f){
  if(document.readyState != "loading") f();
  else document.addEventListener("DOMContentLoaded", f);
})(function(){
  console.log("The Document is ready");
});

Bu, diğer cevapların vermediğini ne ekliyor?
dwjohnston

Bağımsız bir kapak kullanır (genel "pencere" kapsamını doldurmaz), tüm tarayıcılarda çalışır ve çok kompakttır. Bunun gibi başka cevaplar görmüyorum.
Dustin Poissant

Ayrıca, DOM zaten yüklendikten sonra bile çalışır (jQuery.ready gibi), bu cevapların çoğunun yapamadığı.
Dustin Poissant

0

Çoğu vanilya JS Ready işlevi , belge zaten yüklendikten sonraDOMContentLoaded işleyicinin ayarlandığı senaryoyu dikkate almaz - Bu, işlevin hiçbir zaman çalışmayacağı anlamına gelir . Eğer bakmak ise olabilir bir dahilinde dış komut ( ).DOMContentLoadedasync<script async src="file.js"></script>

Aşağıdaki kod DOMContentLoadedyalnızca belgenin readyStatezaten interactiveyoksa veya olup olmadığını kontrol eder complete.

var DOMReady = function(callback) {
  document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback());
};
DOMReady(function() {
  //DOM ready!
});

IE'yi de desteklemek istiyorsanız:

var DOMReady = function(callback) {
    if (document.readyState === "interactive" || document.readyState === "complete") {
        callback();
    } else if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', callback());
    } else if (document.attachEvent) {
        document.attachEvent('onreadystatechange', function() {
            if (document.readyState != 'loading') {
                callback();
            }
        });
    }
};

DOMReady(function() {
  // DOM ready!
});

0

Ben sadece kullanıyorum:

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

Ve document.addEventListener("DOMContentLoaded" //etcen üstteki yanıttan farklı olarak, IE9'a kadar geri çalışır - http://caniuse.com/#search=DOMContentLoaded sadece IE11 kadar yakın bir zamanda gösterir.

İlginç bir şekilde setTimeout2009'da bu çözüme rastladım : DOM aşırılığının hazır olup olmadığını kontrol etmek mi?"Diyelim ki" DOM'un hazır olup olmadığını kontrol etmek için çeşitli çerçevelerin daha karmaşık yaklaşımlarını kullanmak aşırıya kaçıyor mu? "

Bu tekniğin neden işe yaradığına dair en iyi açıklamam, böyle bir setTimeout'a sahip komut dosyasına ulaşıldığında, DOM ayrıştırmanın ortasında olduğu için, setTimeout içinde kodun yürütülmesi bu işlem tamamlanana kadar ertelenir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.