$ (dokumen). Sudah setara tanpa jQuery

2017

Saya memiliki skrip yang menggunakan $(document).ready, tetapi tidak menggunakan apa pun dari jQuery. Saya ingin meringankannya dengan menghapus ketergantungan jQuery.

Bagaimana saya bisa mengimplementasikan $(document).readyfungsionalitas saya sendiri tanpa menggunakan jQuery? Saya tahu bahwa menggunakan window.onloadtidak akan sama, seperti window.onloadkebakaran setelah semua gambar, bingkai, dll. Dimuat.

FlySwat
sumber
296
... dan juga jelas bukan fungsi yang sama.
Joel Mueller
40
Seperti yang dinyatakan oleh jawaban ini , jika semua yang Anda inginkan dari jQuery adalah $(document).ready, Anda dapat menyelesaikan masalah itu dengan mudah dengan menjalankan kode Anda di bagian paling bawah halaman alih-alih di bagian atas. HTML5Boilerplate menggunakan pendekatan yang tepat ini.
Blazemonger
3
Mengapa tidak menggunakan DOMContentLoaded saja? Ini IE9 + caniuse.com/domcontentloaded developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
Brock
Saya menempatkan panggilan saya pada dokumen terakhir dan itu memecahkan masalah saya. Ketika fungsi dipanggil, semuanya dimuat.
IgniteCoders

Jawaban:

1440

Ada pengganti berbasis standar, DOMContentLoadedyang didukung oleh lebih dari 98% browser , meskipun tidak IE8:

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

Fungsi asli jQuery jauh lebih rumit dari sekedar window.onload, seperti yang digambarkan di bawah ini.

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 );
}
Chad Grant
sumber
19
Implementasi javascript biasa yang berfungsi di sini jika seseorang menginginkan kode, mereka dapat langsung masuk: stackoverflow.com/questions/9899372/…
jfriend00
4
Kode siap jQuery DOM tampaknya disederhanakan: github.com/jquery/jquery/blob/master/src/core/ready.js
Jose Nobile
2
@JoseNobile karena mereka menjatuhkan dukungan browser yang lebih lama
huysentruitw
16
Saya pikir kita semua siap untuk pindah dari IE8 ...;). Terima kasih untuk tautannya, @JoseNobile.
Con Antonakos
13
DOMContentLoaded tidak akan berfungsi jika skrip dimuat setelahnya. Dokumen JQuery siap dijalankan selalu.
Jared Insel
343

Edit:

Berikut ini adalah pengganti jQuery yang layak

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

Diambil dari https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/

Fungsi domReady lain yang baik di sini diambil dari https://stackoverflow.com/a/9899701/175071


Karena jawaban yang diterima sangat jauh dari lengkap, saya menjahit fungsi "siap" seperti jQuery.ready()berdasarkan sumber 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;
})();

Cara Penggunaan:

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

Saya tidak yakin seberapa fungsional kode ini, tetapi berfungsi baik dengan tes yang dangkal saya. Ini memakan waktu cukup lama, jadi saya harap Anda dan orang lain dapat memperoleh manfaat darinya.

PS: Saya sarankan kompilasi itu.

Atau Anda dapat menggunakan http://dustindiaz.com/smallest-domready-ever :

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

atau fungsi asli jika Anda hanya perlu mendukung browser baru (Tidak seperti jQuery ready, ini tidak akan berjalan jika Anda menambahkan ini setelah halaman dimuat)

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})
Timo Huovinen
sumber
14
@TimoHuovinen Alternatif: Zepto.js (9,1 kb), Snack.js (8,1 kb), $ dom (2,3 kb), dan 140 Medley (0,5 kb). Sunting: Anda juga bisa melihat Ender.
Frederik Krautwald
2
@FrederikKrautwald $ dom terdengar seperti yang saya inginkan, tetapi tidak yakin apakah itu sesuai dengan tagihan. Zepto juga terlihat sangat menjanjikan, terima kasih telah berbagi!
Timo Huovinen
@TimoHuovinen Jika Anda belum melihat Ender, Anda pasti harus melihatnya, enderjs.com .
Frederik Krautwald
2
@Timo Huovinen: Pertanyaan Anda sangat, sangat luas! Ketika jQuery dibuat, itu dilengkapi banyak masalah lintas browser yang dihasilkan oleh browser yang saat ini kurang signifikan. Saat ini, "hanya javascript" lebih mudah dari sebelumnya. Pada saat ini, membuat "20kb besar terkompresi, yang berisi semua" jelas merupakan ide yang bagus untuk banyak alasan saya memilih untuk tidak mencantumkan semuanya.
dotpush
1
Saya tidak suka ini. Jika orang lebih suka jawaban ini, tanyakan pada diri sendiri mengapa Anda ingin menjatuhkan jQuery di tempat pertama. Agak tidak ada gunanya jika Anda hanya akan mengekstrak fungsionalitas yang sama persis dengan semua yang mundur browser gembung kembali ke bundel Anda. Bukankah itu inti dari menghindari jQuery sejak awal?
Phil
208

Tiga opsi:

  1. Jika scripttag terakhir dari badan, DOM akan siap sebelum tag skrip dieksekusi
  2. Ketika DOM siap, "readyState" akan berubah menjadi "complete"
  3. Letakkan semuanya di bawah pendengar acara 'DOMContentLoaded'

onreadystatechange

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

Sumber: MDN

DOMContentLoaded

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

Khawatir tentang browser zaman batu: Buka kode sumber jQuery dan gunakanreadyfungsinya. Dalam hal ini Anda tidak memparsing + mengeksekusi seluruh perpustakaan yang Anda lakukan hanya sebagian kecil saja.

Jhankar Mahbub
sumber
3
Contoh kedua ini jauh lebih elegan dan ringkas daripada jawaban yang ditandai. Mengapa yang ini tidak ditandai sebagai yang benar?
0112
2
Masih memberi +1 untuk hal DOMContentLoaded, ia melakukan persis apa yang saya inginkan.
tripleee
1
onreadystatechange melakukan trik untuk saya ... diperlukan untuk menjalankan beberapa script setelah memuat jquery async.
Abram
2
Sama seperti FYI, # 1 tidak sepenuhnya benar. Sangat mungkin bagi skrip di akhir halaman untuk memuat sebelum DOM selesai. Itu sebabnya pendengar lebih unggul. Mereka mendengarkan ketika browser selesai. Menempatkannya di ujung adalah memotong jari Anda bahwa skrip memuat lebih lambat dari yang dapat dirender oleh browser.
Machavity
1
varian ini juga akan berfungsi ketika dokumen sudah selesai dimuat, harap perbarui (imo best) jawaban Anda jika Anda dapat: if (document.readyState == 'complete') {init (); } else {document.onreadystatechange = function () {if (document.readyState == 'complete') {init (); }}}
ZPiDER
87

Tempatkan <script>/*JavaScript code*/</script>tepat sebelum </body> tag penutup .

Memang, ini mungkin tidak sesuai dengan tujuan semua orang karena itu membutuhkan mengubah file HTML daripada hanya melakukan sesuatu dalam file JavaScript a la document.ready, tapi masih ...

rampok
sumber
Sepertinya saya ada masalah kompatibilitas, seperti, karena halaman belum siap, Anda tidak dapat melakukan ini atau itu di browser ini dan itu. Sayangnya saya tidak dapat mengingat dengan lebih jelas. Meskipun demikian +1 untuk cara yang cukup dekat di 99% dari semua kasus (dan disarankan oleh Yahoo!).
Boldewyn
7
Sebenarnya, meletakkan elemen skrip di bagian bawah halaman adalah solusi yang hampir sempurna. Ini berfungsi lintas-browser dan mensimulasikan dokumen. Sudah sempurna. Satu-satunya kelemahan adalah bahwa itu (sedikit) lebih menonjol daripada menggunakan beberapa kode pintar, Anda harus bertanya kepada pengguna skrip yang Anda buat untuk menambahkan fragmen skrip tambahan untuk memanggil fungsi siap atau init Anda.
Stijn de Witt
@StijndeWitt - Apa maksud Anda dengan memanggil fungsi init? Sebuah skrip yang menggunakan dokumen. Sudah tidak perlu kode klien lain untuk menyebutnya, itu mandiri, dan setara dengan di mana kode dimasukkan di akhir tubuh juga bisa mandiri dan tidak memerlukan kode lain untuk memanggilnya juga.
nnnnnn
1
Mengapa tidak meletakkan skrip setelah tag penutup, dan sebelum </html>tag penutup ?
Charles Holbrow
1
@CharlesHolbrow Meskipun semua browser akan menafsirkannya dengan benar, jika Anda ingin html yang valid, htmltag hanya boleh berisi headdan body.
Alvaro Montoro
66

Solusi orang miskin:

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

checkLoad();  

Lihat Fiddle

Ditambahkan yang satu ini, sedikit lebih baik kurasa, memiliki cakupan sendiri, dan tidak rekursif

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

Lihat Fiddle

Jakob Sternberg
sumber
8
@ PhilipLangford Atau cukup letakkan di dalam setIntervaldan hapus rekursi sepenuhnya.
Alex W
1
@Raveren, hmm Anda benar, saya cukup yakin saya mengujinya ketika saya mempostingnya. Bagaimanapun, itu hanya menjadi lebih sederhana, sekarang fungsinya dipanggil, tanpa pembungkus.
Jakob Sternberg
24
Ini tidak seksi. Tidak, maaf. Menggunakan pengatur waktu / interval untuk mendeteksi hal-hal dapat "bekerja" tetapi jika Anda terus pemrograman seperti ini proyek yang lebih besar nilainya garam akan menyelam hidung. Jangan meretas hal-hal bersama seperti ini. Kerjakan dengan benar. Silahkan. Kode semacam ini merusak ekosistem pembangunan karena ada solusi yang lebih baik dan Anda TAHU.
dudewad
1
Saya pikir jawaban ini lebih dekat dengan dustindiaz.com/smallest-domready-ever Jadi saya membaik naskah: jsfiddle.net/iegik/PT7x9
iegik
1
@ ReidBlomquist Ya, dan ini adalah cara yang "salah", dan itulah yang saya tunjukkan (walaupun sedikit bersikeras, saya tahu). Anda bisa mengatakan bahwa dengan melakukan kesalahan itu entah bagaimana "membantu" ekosistem, tetapi masalahnya adalah bahwa dengan jumlah kode buruk di luar sana yang diambil orang untuk kode "baik" karena mereka tidak memiliki pengalaman untuk mengetahui lebih baik TIDAK membantu ekosistem, karena dengan begitu mereka akan mengambil kode buruk itu dan mengimplementasikannya menjadi solusi arsitektur produksi yang sebenarnya. Jadi, saya kira, kita harus berbeda pendapat tentang "kekeliruan" ini.
dudewad
34

Saya menggunakan ini:

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

Catatan: Ini mungkin hanya berfungsi dengan browser yang lebih baru, terutama ini: http://caniuse.com/#feat=domcontentloaded

Dustin Davis
sumber
13
IE9 dan di atas sebenarnya
Pascalius
Ini juga berfungsi dengan baik dalam skrip konten Ekstensi Chrome jika Anda mengaitkan document_start atau event document_idle.
Volomike
21

Sungguh, jika Anda hanya peduli dengan Internet Explorer 9+ , kode ini akan cukup untuk menggantikan jQuery.ready:

    document.addEventListener("DOMContentLoaded", callback);

Jika Anda khawatir tentang Internet Explorer 6 dan beberapa browser yang sangat aneh dan langka, ini akan berfungsi:

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

Pertanyaan ini sudah lama ditanyakan. Bagi siapa pun yang hanya melihat pertanyaan ini, sekarang ada situs yang disebut "Anda mungkin tidak perlu jquery" yang rusak - sesuai tingkat dukungan IE yang diperlukan - semua fungsi jquery dan menyediakan beberapa perpustakaan alternatif yang lebih kecil.

Skrip siap dokumen IE8 menurut Anda mungkin tidak perlu jquery

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();
        });
}
chugadie
sumber
Saya bertanya-tanya mengapa 'onreadystatechange'ini perlu daripadadocument.attachEvent('onload', fn);
Lukas
13

Baru-baru ini saya menggunakan ini untuk situs seluler. Ini adalah versi sederhana John Resig dari "Teknik JavaScript Pro". Itu tergantung pada 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;
})();
James
sumber
13
Hati-hati dengan kode ini. Ini TIDAK setara dengan $ (dokumen). Sudah. Kode ini memicu callback ketika document.body siap yang tidak menjamin DOM terisi penuh.
Karolis
12

Peramban silang (peramban lama juga) dan solusi sederhana:

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

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

Menampilkan lansiran di jsfiddle

Pawel
sumber
Kecuali jika dibutuhkan lebih dari 30 ms untuk memuat DOM, kode Anda tidak akan berjalan.
Quelklef
1
@Quelklef yang setInterval tidak setTimeout
Pawel
11

Jawaban jQuery cukup berguna bagi saya. Dengan sedikit pengilangan itu sesuai dengan kebutuhan saya. Saya harap ini membantu orang lain.

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 )
}
Miere
sumber
pada beberapa browser, removeListenerperlu dipanggil dengan dokumen sebagai konteksnya, yaitu. removeListener.call(document, ...
Ron
9

Berikut ini cuplikan kode terkecil untuk menguji DOM ready yang berfungsi di semua browser (bahkan IE 8):

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

Lihat ini jawaban .

Antara Roy
sumber
6

Cukup tambahkan ini ke bagian bawah halaman HTML Anda ...

<script>
    Your_Function();
</script>

Karena, dokumen HTML diuraikan oleh atas-bawah.

davefrassoni
sumber
7
Bagaimana Anda tahu bahwa DOM dibangun ketika kode ini dijalankan? Termasuk CSS yang dimuat dan diurai? Browser API DOMContentLoaded dirancang untuk itu.
Dan
Itu benar-benar tergantung pada apa yang ingin dia lakukan dengan js. Jika dia benar-benar perlu mengeksekusi sesuatu ketika halaman sudah selesai atau belum.
davefrassoni
5

Layak dicari di Rock Solid addEvent () dan http://www.braksator.com/how-to-make-your-own-jquery .

Berikut adalah kode jika situs turun

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");});
Ben
sumber
Tautan kedua rusak.
Peter Mortensen
4

Kode lintas-peramban ini akan memanggil fungsi setelah DOM siap:

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

Begini cara kerjanya:

  1. Baris pertama domReadymemanggil toStringmetode fungsi untuk mendapatkan representasi string dari fungsi yang Anda berikan dan membungkusnya dalam ekspresi yang segera memanggil fungsi.
  2. Sisa dari domReadymembuat elemen skrip dengan ekspresi dan menambahkannya kebody dokumen.
  3. Browser menjalankan tag skrip ditambahkan bodysetelah DOM siap.

Misalnya, jika Anda melakukan ini domReady(function(){alert();});:, berikut ini akan ditambahkan ke bodyelemen:

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

Perhatikan bahwa ini hanya berfungsi untuk fungsi yang ditentukan pengguna. Berikut ini tidak akan berfungsi:domReady(alert);

Max Heiber
sumber
4

Ini tahun 2020 dan <script>tag memiliki deferatribut.

sebagai contoh:

<script src="demo_defer.js" defer></script>

itu menentukan bahwa skrip dieksekusi ketika halaman telah selesai parsing.

https://www.w3schools.com/tags/att_script_defer.asp

Mikser
sumber
3

Bagaimana dengan solusi ini?

// 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();
};
mikrofon
sumber
3
Anda dapat menggunakan addEventListener di jendela dengan "load". Pendengar dieksekusi satu demi satu dan tidak perlu chaining secara manual.
Zaffy
1
Tetapi beban berbeda dari siap. 'Memuat' bahkan terjadi sebelum dokumen 'siap'. Dokumen yang sudah siap memuat DOM-nya, jendela yang dimuat tidak selalu memiliki DOM yang siap. Tapi jawaban yang bagus
Mzn
1
@ Mtz: Saya pikir itu mundur. Saya pikir dokumen siap terjadi sebelum acara memuat jendela. "Secara umum, tidak perlu menunggu semua gambar dimuat penuh. Jika kode dapat dieksekusi lebih awal, biasanya yang terbaik adalah meletakkannya di handler yang dikirim ke metode .ready ()." ( api.jquery.com/load-event )
Tyler Rick
ini akan menimpa sisa window.onload acara di halaman dan akan menyebabkan masalah. itu harus menambahkan acara di atas yang sudah ada.
Teoman shipahi
Acara memuat dapat terjadi terlambat. Sangat menyakitkan untuk menggunakannya saat bergantung pada foto / gambar eksternal pihak ketiga ... Server non-responsif yang tidak Anda kontrol dan semuanya gagal. Menggunakan DOMContentLoaded bukan hanya optimasi, tetapi juga lebih aman!
dotpush
3

Itu selalu baik untuk menggunakan setara JavaScript dibandingkan dengan jQuery. Salah satu alasannya adalah satu perpustakaan lebih sedikit untuk bergantung dan mereka jauh lebih cepat daripada setara jQuery.

Salah satu referensi fantastis untuk setara jQuery adalah http://youmightnotneedjquery.com/ .

Sejauh pertanyaan Anda prihatin, saya mengambil kode di bawah ini dari tautan di atas :) Hanya peringatan apakah itu hanya bekerja dengan Internet Explorer 9 dan yang lebih baru.

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

Paling minimal dan 100% berfungsi

Saya telah mengambil jawaban dari PlainJS dan itu berfungsi dengan baik untuk saya. Itu meluas DOMContentLoadedsehingga dapat diterima di semua browser.


Fungsi ini setara dengan $(document).ready()metode jQuery :

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

Namun, berbeda dengan jQuery, kode ini hanya akan berjalan dengan baik di browser modern (IE> 8) dan itu tidak akan terjadi jika dokumen sudah dirender pada saat skrip ini disisipkan (misalnya melalui Ajax). Karena itu, kita perlu sedikit memperluas ini:

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

Ini pada dasarnya mencakup semua kemungkinan dan merupakan pengganti yang layak untuk pembantu jQuery.

Shivam Sharma
sumber
2

Kami menemukan penerapan lintas peramban kami yang cepat dan kotor yang dapat melakukan trik untuk kebanyakan kasus sederhana dengan penerapan minimal:

window.onReady = function onReady(fn){
    document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};
malko
sumber
apa doc.body!
Nabi KAZ
2

Solusi setTimeout / setInterval yang disajikan di sini hanya akan berfungsi dalam keadaan tertentu.

Masalahnya muncul terutama di versi Internet Explorer yang lebih lama hingga 8.

Variabel yang mempengaruhi keberhasilan solusi setTimeout / setInterval ini adalah:

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

kode asli (Javascript asli) yang menyelesaikan masalah khusus ini ada di sini:

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

ini adalah kode dari mana tim jQuery membangun implementasi mereka.

Diego Perini
sumber
1

Inilah yang saya gunakan, cepat dan mencakup semua basis yang saya pikir; bekerja untuk semuanya kecuali IE <9.

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

Ini sepertinya menangkap semua kasus:

  • segera menyala jika DOM sudah siap (jika DOM tidak "memuat", tetapi "interaktif" atau "lengkap")
  • jika DOM masih memuat, itu mengatur pendengar acara ketika DOM tersedia (interaktif).

Acara DOMContentLoaded tersedia di IE9 dan yang lainnya, jadi saya pribadi berpikir tidak masalah untuk menggunakan ini. Tulis ulang deklarasi fungsi panah ke fungsi anonim biasa jika Anda tidak mengubah kode dari ES2015 ke ES5.

Jika Anda ingin menunggu sampai semua aset dimuat, semua gambar ditampilkan dll, kemudian gunakan window.onload.

Olemak
sumber
1

Jika Anda tidak harus mendukung browser yang sangat lama, berikut adalah cara untuk melakukannya bahkan ketika skrip eksternal Anda dimuat dengan atribut async :

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

Untuk IE9 +:

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

Jika Anda memuat jQuery di dekat bagian bawah BODY, tetapi mengalami masalah dengan kode yang menuliskan jQuery (<func>) atau jQuery (dokumen) .ready (<func>), periksa jqShim di Github.

Alih-alih membuat ulang fungsi siap dokumennya sendiri, ia hanya memegang fungsi-fungsi tersebut sampai jQuery tersedia kemudian dilanjutkan dengan jQuery seperti yang diharapkan. Inti memindahkan jQuery ke bagian bawah tubuh adalah untuk mempercepat pemuatan halaman, dan Anda masih bisa mencapainya dengan menambahkan jqShim.min.js di kepala template Anda.

Saya akhirnya menulis kode ini untuk memindahkan semua skrip di WordPress ke footer, dan kode shim ini sekarang berada langsung di header.

Matt Pileggi
sumber
0

Coba ini:

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

sumber
Lol Anda akan menjalankan panggilan balik dua kali
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 memberikan panggilan balik ketika dom HTML siap untuk sepenuhnya mengakses / mengurai / memanipulasi.

onWinLoad memberikan panggilan balik ketika semuanya telah dimuat (gambar dll)

  • Fungsi-fungsi ini dapat dipanggil kapan saja Anda inginkan.
  • Mendukung banyak "pendengar".
  • Akan berfungsi di browser apa pun.
Jakob Sternberg
sumber
0
(function(f){
  if(document.readyState != "loading") f();
  else document.addEventListener("DOMContentLoaded", f);
})(function(){
  console.log("The Document is ready");
});
Dustin Poissant
sumber
Apa ini menambahkan bahwa jawaban lain tidak?
dwjohnston
Ini menggunakan penutupan mandiri (tidak mengisi lingkup "jendela" global), ia bekerja pada semua browser dan sangat kompak. Saya tidak melihat jawaban lain seperti itu.
Dustin Poissant
Ini juga berfungsi bahkan setelah DOM sudah dimuat (seperti jQuery.ready), yang sebagian besar jawaban ini gagal lakukan.
Dustin Poissant
0

Sebagian besar fungsi JS Ready vanilla TIDAK mempertimbangkan skenario di mana DOMContentLoadedhandler diatur setelah dokumen sudah dimuat - Yang berarti fungsi tidak akan pernah berjalan . Ini dapat terjadi jika Anda mencari di DOMContentLoadeddalam asyncskrip eksternal (<script async src="file.js"></script> ).

Kode di bawah ini memeriksa DOMContentLoadedhanya jika dokumen readyStatebelum interactiveatau complete.

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

Jika Anda ingin mendukung IE juga:

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!
});
Batal
sumber
0

Saya hanya menggunakan:

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

Dan tidak document.addEventListener("DOMContentLoaded" //etcseperti pada jawaban paling atas, ia bekerja sejauh IE9 - http://caniuse.com/#search=DOMContentLoaded hanya menunjukkan baru-baru ini sebagai IE11.

Menariknya saya menemukan setTimeoutsolusi ini pada tahun 2009: Apakah memeriksa kesiapan DOM berlebihan?, yang mungkin bisa dikatakan sedikit lebih baik, seperti yang saya maksudkan "apakah itu berlebihan untuk menggunakan berbagai pendekatan kerangka kerja yang lebih rumit untuk memeriksa kesiapan DOM".

Penjelasan terbaik saya untuk mengapa teknik ini bekerja adalah bahwa, ketika skrip dengan setTimeout telah tercapai, DOM sedang diurai, jadi eksekusi kode dalam setTimeout ditunda sampai operasi selesai.

Dexygen
sumber