¿Cuál es el equivalente no-jQuery de '$ (document) .ready ()'?

444

¿Cuál es el equivalente de no jQuery de $(document).ready()?

TIMEX
fuente
44
Si desea reproducir el $(document).ready()evento de jQuery sin usar ninguna biblioteca, eche un vistazo a esto: stackoverflow.com/questions/1795089/…
CMS
@OP: consulte la página 89 de Técnicas Pro JavaScript para una implementación de JavaScript vainilla de $(document).ready()- books.google.com/… . También utiliza la addEventabstracción de enlace de eventos escrita por Dean Edwards, cuyo código también está en el libro :)
Russ Cam
2
posible duplicado de $ (documento) .ready equivalente sin jQuery
Qantas 94 Heavy

Respuestas:

73

Lo bueno de esto $(document).ready()es que dispara antes window.onload. La función de carga espera hasta que todo se carga, incluidos los activos externos y las imágenes. $(document).ready, sin embargo, se dispara cuando el árbol DOM está completo y puede manipularse. Si desea obtener DOM listo, sin jQuery, puede registrarse en esta biblioteca. Alguien extrajo solo la readyparte de jQuery. Es agradable y pequeño y puede que te resulte útil:

domready en Google Code

Doug Neiner
fuente
44
Red de código DomReady! a través de @CMS en github: github.com/cms/domready/network
Kzqai
45
Esto no responde la pregunta ni muestra ningún código que no sea jQuery. ¿Cómo obtuvo tantos votos a favor?
Daniel W.
3
@DanielW. Porque es simple y práctico. La mayoría de nosotros vino aquí buscando una manera de asegurarnos de que DOM esté listo para ser utilizado por el código javascript.
abarazal
Sí, pero algunos de nosotros vinimos aquí por una respuesta real.
Slbox
613

Esto funciona perfectamente, de ECMA

document.addEventListener("DOMContentLoaded", function() {
  // code...
});

El window.onloadno es igual a JQuery $(document).readyporque $(document).readysolo espera al árbol DOM mientras window.onloadverifica todos los elementos, incluidos los activos externos y las imágenes.

EDITAR : Se agregó IE8 y su equivalente anterior, gracias a la observación de Jan Derk . Puede leer la fuente de este código en MDN en este enlace :

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "interactive") {
        // Initialize your application or run some code.
    }
}

Hay otras opciones aparte de "interactive". Vea el enlace de MDN para más detalles.

sospedra
fuente
De acuerdo con Benjamin. No puede simplemente usar attachEvent. Por ejemplo, en Chrome obtienes: Tipo de error no detectado: document.attachEvent no es una función. Use la respuesta vinculada de Jan Derk.
Manuel Arwed Schmidt
99
¿Qué pasa si el documento ya está cargado cuando se llama a este script? Nada sucederá en absoluto :(
oriadam
8
@Deerloper Nope, acabo de probarlo en la consola Chrome - no pasó nada: document.addEventListener("DOMContentLoaded",function(){console.log(123)})pruébalo ahora
oriadam
2
Soporte de DOMContent Cargado en navegadores: caniuse.com/domcontentloaded
Guillaume Husta
1
@elliottregan es cierto. Elimino el comentario para evitar contaminar este hilo. Sugiero que todos hagan lo mismo :) Y dejen un comentario si es necesario señalando el comentario si es necesario. Dado que es un extra porque va más allá de las preguntas de OC
sospedra
43

Una cosita que armé

domready.js

(function(exports, d) {
  function domReady(fn, context) {

    function onReady(event) {
      d.removeEventListener("DOMContentLoaded", onReady);
      fn.call(context || exports, event);
    }

    function onReadyIe(event) {
      if (d.readyState === "complete") {
        d.detachEvent("onreadystatechange", onReadyIe);
        fn.call(context || exports, event);
      }
    }

    d.addEventListener && d.addEventListener("DOMContentLoaded", onReady) ||
    d.attachEvent      && d.attachEvent("onreadystatechange", onReadyIe);
  }

  exports.domReady = domReady;
})(window, document);

Cómo usarlo

<script src="domready.js"></script>
<script>
  domReady(function(event) {
    alert("dom is ready!");
  });
</script>

También puede cambiar el contexto en el que se ejecuta la devolución de llamada pasando un segundo argumento

function init(event) {
  alert("check the console");
  this.log(event);
}

domReady(init, console);
Gracias
fuente
2
Gracias. Me gusta el hecho de que es compatible con versiones anteriores. Seguir adelante no significa simplemente dejar atrás a las personas menos afortunadas. No poder usar un navegador moderno (por cualquier razón) es desafortunado ...
CO
28

Ahora que es 2018, aquí hay un método rápido y simple.

Esto agregará un detector de eventos, pero si ya se activó, comprobaremos que el dom esté listo o que esté completo. Esto puede activarse antes o después de que los recursos secundarios hayan terminado de cargarse (imágenes, hojas de estilo, marcos, etc.).

function domReady(fn) {
  // If we're early to the party
  document.addEventListener("DOMContentLoaded", fn);
  // If late; I mean on time.
  if (document.readyState === "interactive" || document.readyState === "complete" ) {
    fn();
  }
}

domReady(() => console.log("DOM is ready, come and get it!"));

Lecturas adicionales


Actualizar

Aquí hay algunos ayudantes de utilidad rápida que usan ES6 Import & Export estándar que escribí que también incluyen TypeScript. Tal vez pueda hacer que estos sean una biblioteca rápida que se pueda instalar en proyectos como una dependencia.

JavaScript

export const domReady = (callBack) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

Mecanografiado

export const domReady = (callBack: () => void) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack: () => void) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

Promesas

export const domReady = new Promise(resolve => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', resolve);
  }
  else {
    resolve();
  }
});

export const windowReady = new Promise(resolve => {
  if (document.readyState === 'complete') {
    resolve();
  }
  else {
    window.addEventListener('load', resolve);
  }
});
CTS_AE
fuente
16

De acuerdo con http://youmightnotneedjquery.com/#ready, un buen reemplazo que todavía funciona con IE8 es

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

// test
window.ready(function() {
    alert('it works');
});

mejoras : Personalmente, también verificaría si el tipo de fnes una función. Y como @elliottregan sugirió eliminar el detector de eventos después de su uso.

La razón por la que respondo esta pregunta tarde es porque estaba buscando esta respuesta pero no pude encontrarla aquí. Y creo que esta es la mejor solución.

en línea Thomas
fuente
1
Sí, esta es la mejor respuesta en mi opinión. Fácil de leer, y ejecuta el código incluso si el DOM ya está cargado. Lo único que agregaría es eliminar el detector de eventos después de que se active el evento.
elliottregan
14

Hay un reemplazo basado en estándares, DOMContentLoaded , que es compatible con más del 90% de los navegadores, pero no con IE8 (por lo tanto, el siguiente código lo usa JQuery para el soporte del navegador) :

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

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 );
}
Zigri2612
fuente
1
Nueva jQuery abandonado el soporte para navegadores antiguos y ahora sólo tienen DOMContentLoadedy loadeventos usando addEventListener, y lo primero que el fuego eliminar los dos detectores, por lo que no se activan dos veces.
jcubic
8

En JavaScript simple, sin bibliotecas? Es un error$es simplemente un identificador y no está definido a menos que lo defina.

jQuery define $como su propio "objeto todo" (también conocido como jQuerypara que pueda usarlo sin entrar en conflicto con otras bibliotecas). Si no está utilizando jQuery (o alguna otra biblioteca que lo defina), $no se definirá.

¿O pregunta cuál es el equivalente en JavaScript simple? En ese caso, probablemente desee window.onload, que no es exactamente equivalente, pero es la forma más rápida y fácil de acercarse al mismo efecto en JavaScript de vainilla.

Brian Campbell
fuente
39
Para los que votaron a favor de esta respuesta (y las otras a continuación): cuando se hizo esta pregunta, simplemente dijo: "¿Qué es $ (document) .ready () en javascript? No jquery. ¿Qué es?" Parecía que estaba preguntando qué significaba eso en JavaScript simple y sin jQuery cargado. En mi respuesta, intenté responder esa pregunta, así como dar la respuesta fácil más cercana para JavaScript simple sin jQuery u otras bibliotecas en caso de que eso sea lo que quiso decir. Tenga en cuenta que todo el contexto adicional fue agregado por otras personas que adivinaron lo que estaba haciendo la pregunta, no el póster original.
Brian Campbell el
5

La forma más fácil en los navegadores recientes sería utilizar los GlobalEventHandlers apropiados , onDOMContentLoaded , onload , onloadeddata (...)

onDOMContentLoaded = (function(){ console.log("DOM ready!") })()

onload = (function(){ console.log("Page fully loaded!") })()

onloadeddata = (function(){ console.log("Data loaded!") })()

El evento DOMContentLoaded se activa cuando el documento HTML inicial se ha cargado y analizado por completo, sin esperar a que las hojas de estilo, las imágenes y los subtramas finalicen la carga. Se debe usar una carga de evento muy diferente solo para detectar una página completamente cargada. Es un error increíblemente popular usar load donde DOMContentLoaded sería mucho más apropiado, así que tenga cuidado.

https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

La función utilizada es un IIFE, muy útil en este caso, ya que se activa cuando está listo:

https://en.wikipedia.org/wiki/Immediately-invoked_function_expression

Obviamente, es más apropiado colocarlo al final de cualquier script.

En ES6, también podemos escribirlo como una función de flecha:

onload = (() => { console.log("ES6 page fully loaded!") })()

Lo mejor es usar los elementos DOM, podemos esperar a que cualquier variable esté lista, que desencadenará un IIFE con flecha.

El comportamiento será el mismo, pero con menos impacto en la memoria.

footer = (() => { console.log("Footer loaded!") })()
<div id="footer">

En muchos casos, el objeto del documento también se activa cuando está listo , al menos en mi navegador. La sintaxis es muy buena, pero necesita más pruebas sobre compatibilidades.

document=(()=>{    /*Ready*/   })()
NVRM
fuente
¿Podría un IIFE dispararse antes de que el DOM termine de cargar elementos después de él?
CTS_AE
Claro, es solo una función, una función anónima, en un cierre.
NVRM
0

El cuerpo onLoad también podría ser una alternativa:

<html>
<head><title>Body onLoad Exmaple</title>

<script type="text/javascript">
    function window_onload() {
        //do something
    }
</script>

</head>
<body onLoad="window_onload()">

</body>
</html>
joan16v
fuente