$ (documento) .ready equivalente sin jQuery

Tengo un script que usa $(document).ready, pero no usa nada más de jQuery. Me gustaría aligerarlo eliminando la dependencia de jQuery.

¿Cómo puedo implementar el mío? $(document).ready funcionalidad sin usar jQuery? Yo se que usando window.onload no será lo mismo, ya que window.onload se dispara después de que se hayan cargado todas las imágenes, fotogramas, etc.

preguntado el 28 de abril de 09 a las 18:04

... y definitivamente tampoco la misma funcionalidad. -

As esta respuesta estados, si todo lo que quieres de jQuery es $(document).ready, puede resolver ese problema fácilmente ejecutando su código en la parte inferior de la página en lugar de en la parte superior. HTML5Repetitivo utiliza este enfoque exacto. -

Puse mi llamada por fin de documento y eso solucionó mi problema. Cuando se llama a la función, todo se carga. -

30 Respuestas

Hay un reemplazo basado en estándares,DOMContentLoaded que es apoyado por más 98% de los navegadores, aunque no IE8:

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

La función nativa de jQuery es mucho más complicada que solo window.onload, como se muestra a continuación.

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

respondido 14 mar '17, 01:03

Una implementación real de JavaScript simple y funcional aquí si alguien quiere un código que simplemente puede ingresar: stackoverflow.com/questions/9899372/… - amigo00

El código jQuery DOM ready parece estar simplificado: github.com/jquery/jquery/blob/master/src/core/ready.js - José Nobile

@JoseNobile porque dejaron de admitir navegadores más antiguos - huysentruitw

Creo que todos estamos listos para pasar de IE8 ...;). Gracias por el enlace, @JoseNobile. - Con Antonakos

DOMContentLoaded no funcionará si el script se carga posteriormente. JQuery document ready se ejecuta siempre. - Jared Insel

Edit:

Aquí hay un reemplazo viable para jQuery listo

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

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

Otra buena función domReady aquí tomado de https://stackoverflow.com/a/9899701/175071


Como la respuesta aceptada estaba muy lejos de ser completa, combiné una función "lista" como jQuery.ready() basado en la fuente 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;
})();

Modo de empleo:

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

No estoy seguro de cuán funcional es este código, pero funcionó bien con mis pruebas superficiales. Esto tomó bastante tiempo, así que espero que usted y otros puedan beneficiarse de él.

PD: sugiero compilar él.

O puede utilizar http://dustindiaz.com/smallest-domready-ever:

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

o la función nativa si solo necesita admitir los nuevos navegadores (a diferencia de jQuery ready, esto no se ejecutará si agrega esto después de que la página se haya cargado)

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

Respondido 29 ago 18, 07:08

@TimoHuovinen Alternativas: Zepto.js (9.1 kb), Snack.js (8.1 kb), $ dom (2.3 kb) y 140 Medley (0.5 kb). Edit: También podrías echarle un vistazo a Ender. - Federico Krautwald

@FrederikKrautwald $ dom suena como lo que me gustaría, pero no estoy seguro de si se ajusta a los requisitos. Zepto también parece muy prometedor, ¡gracias por compartir! - Timo Huovinen

@TimoHuovinen Si no has mirado a Ender, definitivamente deberías echarle un vistazo, enderjs.com. - Federico Krautwald

@Timo Huovinen: ¡Tu pregunta es muy, muy amplia! Cuando se creó jQuery, se adaptó a muchos problemas de navegadores cruzados generados por navegadores que hoy en día son menos importantes. Hoy en día, "solo javascript" es más fácil de lo que era. En este momento, crear un "gran tamaño comprimido de 20kb, que contenga todo" fue sin duda una buena idea por tantas razones que prefiero no enumerarlos todos. - empuje de puntos

No me gusta esto. Si la gente prefiere esta respuesta, pregúntese por qué quiere eliminar jQuery en primer lugar. Es un poco inútil si solo va a extraer exactamente la misma funcionalidad con todo el respaldo del navegador en su paquete. ¿No es ese el objetivo de evitar jQuery en primer lugar? - Phil

Tres opciones:

  1. If script es la última etiqueta del cuerpo, el DOM estaría listo antes de que se ejecute la etiqueta del script
  2. Cuando el DOM esté listo, "readyState" cambiará a "complete"
  3. Ponga todo en el detector de eventos 'DOMContentLoaded'

onreadystatechange

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

Fuente: DND

DOMContentLoaded

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

Preocupado por los navegadores de la edad de piedra: Vaya al código fuente de jQuery y use el ready función. En ese caso, no está analizando + ejecutando toda la biblioteca, solo está haciendo una parte muy pequeña de ella.

Respondido 24 Abr '16, 12:04

Este segundo ejemplo es mucho más elegante y conciso que las respuestas marcadas. ¿Por qué no se marcó este como el correcto? - 0112

Aún con +1 para DOMContentLoaded, hizo exactamente lo que quería. - triples

onreadystatechange hizo el truco para mí ... necesitaba ejecutar un script después de la carga asíncrona de jquery. - Abram

Al igual que un FYI, el n. ° 1 no es del todo cierto. Es muy posible que se cargue una secuencia de comandos al final de la página antes de que se complete el DOM. Por eso los oyentes son superiores. Escuchan cuando el navegador está listo. Ponerlo al final es cruzar los dedos de que la carga del script fue más lenta de lo que el navegador puede procesar. - Macavidad ♦

esta variante también funcionará cuando el documento ya haya terminado de cargarse, actualice su (en mi opinión la mejor) respuesta si puede: if (document.readyState == 'complete') {init (); } else {document.onreadystatechange = function () {if (document.readyState == 'complete') {init (); }}} - ZPiDER

Añada el <script>/*JavaScript code*/</script> Derecho antes del cierre </body> etiqueta.

Es cierto que esto puede no ser adecuado para los propósitos de todos, ya que requiere cambiar el archivo HTML en lugar de simplemente hacer algo en el archivo JavaScript a la document.ready, pero aún...

Respondido 24 Abr '16, 12:04

Me parece que hubo problemas de compatibilidad, como que, dado que la página aún no está lista, no se puede hacer esto o aquello en estos y aquellos navegadores. Lamentablemente, no puedo recordarlo con más claridad. No obstante, haga +1 para una forma que sea lo suficientemente cercana en el 99% de todos los casos (y sugerida por Yahoo!). - Boldewyn

De hecho, poner un elemento de secuencia de comandos al final de la página es una solución casi perfecta. Funciona en varios navegadores y simula document.Ready perfecto. La única desventaja es que es (un poco) más molesto que usar un código inteligente, tendrá que pedirle al usuario del script que está creando que agregue un fragmento de script adicional para llamar a su función ready o init. - Stijn de Witt

Por que no poner el guion después de la etiqueta del cuerpo de cierre, y antes del cierre </html> ¿etiqueta? - Carlos Holbrow

@CharlesHolbrow Aunque todos los navegadores lo interpretarán correctamente, si desea que sea un html válido, html la etiqueta solo debe contener head y body. - Álvaro Montoro

@StijndeWitt, hay un caso peculiar cuando difieren. Si establece un MutaciónObservador y no lo envuelvas con document.ready, atrapará todo entre el cierre </script> y cierre </body> etiquetas. Incluso si es solo un espacio en blanco, en este caso informará de un nodo de texto insertado. Recientemente me encontré con esto y me sorprendió mucho. - 1234ru

La solución del pobre:

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

checkLoad();  

Ver violín

Agregué este, un poco mejor, supongo, con alcance propio y no recursivo

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

Ver violín

Respondido 27 Jul 15, 19:07

@PhilipLangford O simplemente póngalo dentro de un setInterval y elimine la recursividad por completo. - alex w

@Raveren, hmm, tienes razón, estoy bastante seguro de que lo probé cuando lo publiqué. de todos modos, solo se volvió aún más simple, ahora la función acaba de ser llamada, sin envoltura. - Jakob Sternberg

Esto no es sexy. No lo siento. El uso de temporizadores / intervalos para detectar cosas puede "funcionar", pero si sigues programando así, cualquier proyecto más grande que se precie se hundirá. No hackear cosas juntas como esta. Hazlo bien. Por favor. Este tipo de código daña el ecosistema de desarrollo porque hay una mejor solución y lo SABES. - amigo

Creo que esta respuesta se acerca mucho más a dustindiaz.com/smallest-domready-ever Así que mejoré el guión: jsfiddle.net/iegik/PT7x9 - iegik

@ReidBlomquist Sí, y esta es una forma "incorrecta", y eso es lo que estoy señalando (aunque un poco categóricamente, lo sé). Se podría decir que hacerlo mal de alguna manera está "ayudando" al ecosistema, pero el problema es que con la cantidad de código incorrecto que la gente toma por código "bueno" porque no tienen la experiencia para saber nada mejor NO ayuda al ecosistema, porque entonces tomarán ese código incorrecto y lo implementarán en una solución arquitectónica de producción real. Entonces, supongo, tendremos que diferir de opinión sobre esta "falacia". - amigo

Yo uso esto:

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

Nota: esto probablemente solo funcione con los navegadores más nuevos, especialmente estos: http://caniuse.com/#feat=domcontentloaded

Respondido 24 Abr '16, 12:04

IE9 y superior en realidad - pascalius

Esto también funciona muy bien en los scripts de contenido de la extensión de Chrome si estaba conectando el evento document_start o document_idle. - Volomike

De verdad, si te preocupas por Internet Explorer 9+ solo, este código sería suficiente para reemplazar jQuery.ready:

    document.addEventListener("DOMContentLoaded", callback);

Si te preocupas por Internet Explorer 6 y algunos navegadores realmente extraños y raros, esto funcionará:

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

Respondido 24 Abr '16, 12:04

Esta pregunta se hizo hace bastante tiempo. Para cualquiera que vea esta pregunta, ahora hay un sitio llamado "es posible que no necesite jquery" que desglosa, según el nivel de soporte de IE requerido, toda la funcionalidad de jquery y proporciona algunas bibliotecas alternativas más pequeñas.

Script IE8 listo para documentos de acuerdo con puede que no necesites 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();
        });
}

Respondido 28 Jul 15, 10:07

Me pregunto porque el 'onreadystatechange' es necesario en lugar de document.attachEvent('onload', fn); - Lucas

Recientemente estuve usando esto para un sitio móvil. Esta es la versión simplificada de John Resig de "Pro JavaScript Techniques". Depende de 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;
})();

respondido 04 nov., 11:01

Tenga cuidado con este código. NO es equivalente a $ (document) .ready. Este código activa la devolución de llamada cuando document.body está listo, lo que no garantiza que el DOM esté completamente cargado. - talón

Es el año 2020 y <script> la etiqueta tiene defer atributo.

por ejemplo:

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

especifica que el script se ejecuta cuando la página ha terminado de analizarse.

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

Respondido el 23 de enero de 20 a las 22:01

agradable, pero solo para scripts externos. - marioelerizo

Cross-browser (navegadores antiguos también) y una solución simple:

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

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

Mostrando alerta en jsfiddle

contestado el 09 de mayo de 16 a las 19:05

Excepto si se necesitan más de 30 ms para cargar el DOM, el código no se ejecutará. - Quelklef

@Quelklef que es setInterval no setTimeout - Pawel

La respuesta de jQuery fue bastante útil para mí. Con un poco de refactoría se adaptó bien a mis necesidades. Espero que ayude a alguien más.

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

Respondido el 05 de Septiembre de 12 a las 17:09

en algunos navegadores, el removeListener deberá llamarse con el documento como contexto, es decir. removeListener.call(document, ... - Ron

Aquí está la fragmento de código más pequeño para probar DOM listo que funciona en todos los navegadores (incluso IE 8):

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

Ver este https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be.

contestado el 23 de mayo de 17 a las 13:05

Simplemente agregue esto al final de su página HTML ...

<script>
    Your_Function();
</script>

Porque, los documentos HTML se analizan de arriba a abajo.

Respondido 24 Abr '16, 12:04

¿Cómo sabe que DOM se construye cuando se ejecuta este código? ¿Incluyendo CSS cargado y analizado? La API del navegador DOMContentLoaded está diseñada para eso. - Dan

Realmente depende de lo que quiera hacer con js. Si realmente necesita ejecutar algo cuando la página haya terminado o no. - Davefrassoni

Vale la pena mirar en Rock Solid addEvent () y http://www.braksator.com/how-to-make-your-own-jquery.

Aquí está el código en caso de que el sitio se caiga

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

Respondido 24 Abr '16, 12:04

Lo más mínimo y 100% funcional

He elegido la respuesta de PlainJS y me está funcionando bien. Se extiende DOMContentLoaded para que sea aceptado en todos los navegadores.


Esta función es equivalente a la de jQuery $(document).ready() método:

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

Sin embargo, a diferencia de jQuery, este código solo se ejecutará correctamente en navegadores modernos (IE> 8) y no lo hará en caso de que el documento ya esté renderizado en el momento en que se inserta este script (por ejemplo, a través de Ajax). Por lo tanto, necesitamos extender esto un poco:

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

Esto cubre básicamente todas las posibilidades y es un reemplazo viable para el asistente de jQuery.

Respondido el 30 de Septiembre de 19 a las 07:09

Este código de navegador cruzado llamará a una función una vez que el DOM esté listo:

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

Así es como funciona:

  1. La primera linea de domReady llama al toString método de la función para obtener una representación de cadena de la función que pasa y la envuelve en una expresión que llama inmediatamente a la función.
  2. El resto de los domReady crea un elemento de secuencia de comandos con la expresión y lo agrega a la body del documento
  3. El navegador ejecuta etiquetas de secuencia de comandos adjuntas a body después de que el DOM esté listo.

Por ejemplo, si hace esto: domReady(function(){alert();});, lo siguiente se adjuntará al body elemento:

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

Tenga en cuenta que esto solo funciona para funciones definidas por el usuario. Lo siguiente no funcionará: domReady(alert);

Respondido el 27 de diciembre de 14 a las 17:12

Siempre es bueno usar equivalentes de JavaScript en comparación con jQuery. Una razón es una biblioteca menos de la que depender y son mucho más rápidas que las equivalentes de jQuery.

Una referencia fantástica para los equivalentes de jQuery es http://youmightnotneedjquery.com/.

En lo que respecta a su pregunta, tomé el siguiente código del enlace anterior :) La única advertencia es que solo funciona con Internet Explorer 9 y después.

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

Respondido 24 Abr '16, 12:04

¿Qué tal esta solución?

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

Respondido 17 ago 12, 08:08

Puede usar addEventListener en la ventana con "cargar". Los oyentes se ejecutan uno tras uno y no necesitan encadenamiento manual. - Zaffy

Pero la carga es diferente a la lista. La 'carga' ocurre incluso antes de que el documento esté 'listo'. Un documento listo tiene su DOM cargado, una ventana cargada no necesariamente tiene el DOM listo. Sin embargo, buena respuesta - mzn

@Mzn: Creo que eso es al revés. Creo que el documento listo sucede antes el evento de carga de la ventana. "En general, no es necesario esperar a que todas las imágenes se carguen por completo. Si el código se puede ejecutar antes, generalmente es mejor colocarlo en un controlador enviado al método .ready ()". (api.jquery.com/load-event) - tyler rick

esto anulará el resto de los eventos window.onload en la página y causaría problemas. debería agregar un evento sobre el existente. - teoman shipahi

El evento de carga puede ocurrir demasiado tarde. Es doloroso usarlo cuando depende de js / imágenes externas de terceros ... Un servidor que no responde que no controla y todo falla. Usar DOMContentLoaded no es solo una optimización, ¡también es más seguro! - empuje de puntos

Encontramos una implementación cruzada de navegadores rápida y sucia que puede funcionar para la mayoría de los casos simples con una implementación mínima:

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

Respondido 24 Abr '16, 12:04

lo que es doc.body !? - Nabi KAZ

Si no tiene que admitir navegadores muy antiguos, aquí hay una manera de hacerlo incluso cuando su secuencia de comandos externa esté cargada con Asincrónico atributo:

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

Respondido 22 Oct 17, 08:10

Yo simplemente uso:

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

Y a diferencia de document.addEventListener("DOMContentLoaded" //etc como en la respuesta principal, funciona desde IE9 - http://caniuse.com/#search=DOMContentLoaded solo indica tan recientemente como IE11.

Curiosamente me topé con esto setTimeout solución en 2009: ¿Es excesivo comprobar la disponibilidad del DOM?, que probablemente podría haberse redactado un poco mejor, ya que quise decir "¿es exagerado usar los enfoques más complicados de varios marcos para verificar la preparación del DOM?".

Mi mejor explicación de por qué funciona esta técnica es que, cuando se ha alcanzado el script con tal setTimeout, el DOM está en medio de ser analizado, por lo que la ejecución del código dentro del setTimeout se pospone hasta que finaliza la operación.

Respondido el 13 de diciembre de 19 a las 13:12

Comparación

Aquí (en el fragmento de abajo) hay una comparación de los métodos "incorporados" del navegador disponibles elegidos y su secuencia de ejecución. Observaciones

  • al document.onload (X) no es compatible con ningún navegador moderno (el evento nunca se encendido)
  • si usas <body onload="bodyOnLoad()"> (F) y al mismo tiempo window.onload (E) entonces solo se ejecutará el primero (porque anula el segundo)
  • controlador de eventos dado en <body onload="..."> (F) está envuelto por adicionales onload función
  • document.onreadystatechange (D) no anular document .addEventListener('readystatechange'...) (C) probablemente cecasue onXYZevent-like los métodos son independientes de addEventListener colas (lo que permite agregar múltiples oyentes). Probablemente no ocurra nada entre la ejecución de estos dos controladores.
  • todos los scripts escriben su marca de tiempo en la consola, pero los scripts que también tienen acceso a div escriba sus marcas de tiempo también en el cuerpo (haga clic en el enlace "Página completa" después de la ejecución del script para verlo).
  • soluciones readystatechange (C, D) se ejecutan varias veces por el navegador, pero para diferentes estados de documento:
  • carga - el documento se está cargando (no se disparó en el fragmento)
  • interactivo - el documento se analiza, se dispara antes DOMContentLoaded
  • completar - el documento y los recursos se cargan, se disparan antes body/window onload

<html>

<head>
  <script>
    // solution A
    console.log(`[timestamp: ${Date.now()}] A: Head script`) ;
    
    // solution B
    document.addEventListener("DOMContentLoaded", () => {
      print(`[timestamp: ${Date.now()}] B: DOMContentLoaded`);
    });

    // solution C
    document.addEventListener('readystatechange', () => {
      print(`[timestamp: ${Date.now()}] C: ReadyState: ${document.readyState}`);
    });
   
    // solution D
    document.onreadystatechange = s=> {print(`[timestamp: ${Date.now()}] D: document.onreadystatechange ReadyState: ${document.readyState}`)};
    
    // solution E (never executed)
    window.onload = () => {
      print(`E: <body onload="..."> override this handler`);
    };

    // solution F
    function bodyOnLoad() {
      print(`[timestamp: ${Date.now()}] F: <body onload='...'>`);      
      infoAboutOnLoad(); // additional info
    }
    
    // solution X
    document.onload = () => {print(`document.onload is never fired`)};



    // HELPERS

    function print(txt) { 
      console.log(txt);
      if(mydiv) mydiv.innerHTML += txt.replace('<','&lt;').replace('>','&gt;') + '<br>';
    }
    
    function infoAboutOnLoad() {
      console.log("window.onload (after  override):", (''+document.body.onload).replace(/\s+/g,' '));
      console.log(`body.onload==window.onload --> ${document.body.onload==window.onload}`);
    }
            
    console.log("window.onload (before override):", (''+document.body.onload).replace(/\s+/g,' '));

  </script>
</head>

<body onload="bodyOnLoad()">
  <div id="mydiv"></div>

  <!-- this script must te at the bottom of <body> -->
  <script>
    // solution G
    print(`[timestamp: ${Date.now()}] G: <body> bottom script`);
  </script>
</body>

</html>

Respondido 20 ago 20, 21:08

Esto es lo que uso, es rápido y cubre todas las bases, creo; funciona para todo excepto IE <9.

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

Esto parece atrapar todos los casos:

  • se activa inmediatamente si el DOM ya está listo (si el DOM no está "cargando", sino "interactivo" o "completo")
  • si el DOM todavía se está cargando, configura un detector de eventos para cuando el DOM esté disponible (interactivo).

El evento DOMContentLoaded está disponible en IE9 y todo lo demás, así que personalmente creo que está bien usarlo. Vuelva a escribir la declaración de la función de flecha a una función anónima normal si no está transpilando su código de ES2015 a ES5.

Si desea esperar hasta que se carguen todos los activos, se muestren todas las imágenes, etc., utilice window.onload en su lugar.

Respondido 07 Jul 16, 14:07

Las soluciones setTimeout / setInterval presentadas aquí solo funcionarán en circunstancias específicas.

El problema aparece especialmente en versiones anteriores de Internet Explorer hasta la 8.

Las variables que afectan el éxito de estas soluciones setTimeout / setInterval son:

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

el código original (Javascript nativo) que resuelve este problema específico está aquí:

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

este es el código a partir del cual el equipo de jQuery ha construido su implementación.

Respondido 14 ago 16, 12:08

Para IE9 +:

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

Respondido 03 Feb 16, 15:02

Si está cargando jQuery cerca de la parte inferior de BODY, pero tiene problemas con el código que escribe jQuery ( ) o jQuery (documento) .ready ( ), verificar jqShim en Github.

En lugar de recrear su propia función preparada para documentos, simplemente se aferra a las funciones hasta que jQuery esté disponible y luego procede con jQuery como se esperaba. El objetivo de mover jQuery a la parte inferior del cuerpo es acelerar la carga de la página, y aún puede lograrlo insertando jqShim.min.js en el encabezado de su plantilla.

Terminé escribiendo este código para mover todos los scripts en WordPress al pie de página, y solo este código de corrección ahora se encuentra directamente en el encabezado.

Respondido 24 Abr '16, 12:04

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

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

onDocReady proporciona una devolución de llamada cuando el dom HTML está listo para acceder / analizar / manipular por completo.

onWinLoad proporciona una devolución de llamada cuando todo se ha cargado (imágenes, etc.)

  • Estas funciones se pueden llamar cuando lo desee.
  • Soporta múltiples "oyentes".
  • Funcionará en cualquier navegador.

contestado el 28 de mayo de 18 a las 23:05

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

respondido 27 nov., 18:21

¿Qué agrega esto que las otras respuestas no? - Dwjohnston

Utiliza un cierre autónomo (no llena el alcance de la "ventana" global), funciona en todos los navegadores y es muy compacto. No veo ninguna otra respuesta como esta. - Dustin Poissant

También funciona incluso después de que el DOM ya se haya cargado (como lo hace jQuery.ready), lo que la mayoría de estas respuestas no logran. - Dustin Poissant

La mayoría de las funciones vanilla JS Ready NO consideran el escenario donde el DOMContentLoaded el controlador está configurado después de el documento ya está cargado, lo que significa que la función nunca corras. Esto puede suceder si busca DOMContentLoaded dentro de una async guión externo<script async src="file.js"></script>).

El siguiente código comprueba DOMContentLoaded solo si el documento es readyState no es ya interactive or complete.

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

Si también desea admitir IE:

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

Respondido 12 Abr '19, 17:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.