Qual è l'equivalente non jQuery di '$ (document) .ready ()'?


444

Qual è l'equivalente non jQuery di $(document).ready()?


4
Se vuoi riprodurre l' $(document).ready()evento di jQuery senza usare alcuna libreria, dai un'occhiata a: stackoverflow.com/questions/1795089/…
CMS

@OP: consulta la pagina 89 di Pro JavaScript Techniques per un'implementazione JavaScript vanilla di $(document).ready()- books.google.com/… . Utilizza anche l' addEventastrazione vincolante dell'evento scritta da Dean Edwards, il cui codice è anche nel libro :)
Russ Cam

Risposte:


73

La cosa bella $(document).ready()è che spara prima window.onload. La funzione di caricamento attende fino a quando non viene caricato tutto, incluse risorse e immagini esterne. $(document).ready, tuttavia, viene generato quando l'albero DOM è completo e può essere manipolato. Se vuoi raggiungere il DOM pronto, senza jQuery, puoi controllare in questa libreria. Qualcuno ha estratto solo la readyparte da jQuery. È bello e piccolo e potresti trovarlo utile:

già su Google Code


4
Rete di codici DomReady! via @CMS su github: github.com/cms/domready/network
Kzqai

45
Questo non risponde alla domanda né mostra alcun codice non jQuery. Come ha ottenuto così tanti voti positivi?
Daniel W.

3
@DanielW. Perché è semplice e pratico. Molti di noi sono venuti qui alla ricerca di un modo per assicurarsi che DOM sia pronto per essere utilizzato dal codice javascript.
abarazal

Sì, ma alcuni di noi sono venuti qui per una vera risposta.
Slbox

614

Funziona perfettamente, dall'ECMA

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

Il window.onloadnon è uguale a JQuery $(document).readyperché $(document).readyattende solo l'albero del DOM mentre window.onloadcontrolla tutti gli elementi inclusi risorse e immagini esterne.

EDIT : aggiunto IE8 e equivalente precedente, grazie all'osservazione di Jan Derk . Puoi leggere la fonte di questo codice su MDN a questo link :

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

Ci sono altre opzioni oltre a "interactive". Vedi il link MDN per i dettagli.


D'accordo con Benjamin. Non puoi semplicemente usare attachEvent. Ad esempio, in Chrome viene visualizzato: Uncaught TypeError: document.attachEvent non è una funzione. Usa la risposta collegata di Jan Derk.
Manuel Arwed Schmidt,

9
Cosa succede se il documento è già stato caricato quando viene chiamato questo script? Non succederà nulla :(
oriadam,

8
@Deerloper No, l'ho appena provato sulla console Chrome - non è successo niente: document.addEventListener("DOMContentLoaded",function(){console.log(123)})provalo ora
oriadam

2
Supporto di DOMContentCaricato nei browser: caniuse.com/domcontentloaded
Guillaume Husta,

1
@elliottregan è vero rimuovo il commento per evitare di inquinare questo thread, suggerisco a tutti di fare lo stesso :) e di lasciare un commento se necessario sottolineando il commento se necessario. Dal momento che è un extra perché va oltre le domande OC
sospedra

43

Una piccola cosa che ho messo insieme

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

Come usarlo

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

È inoltre possibile modificare il contesto in cui viene eseguito il callback passando un secondo argomento

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

domReady(init, console);

2
Grazie. Mi piace il fatto che sia compatibile con le versioni precedenti. Andare avanti non significa lasciare alle spalle persone meno fortunate. Non essere in grado di utilizzare un browser moderno (per qualsiasi motivo) è sfortunato ...
CO

28

Ora che è il 2018 ecco un metodo rapido e semplice.

Ciò aggiungerà un listener di eventi, ma se è già stato attivato verificheremo che il dom è in uno stato pronto o che è completo. Questo può attivarsi prima o dopo il completamento del caricamento delle risorse secondarie (immagini, fogli di stile, cornici, ecc.).

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

Letture aggiuntive


Aggiornare

Ecco alcuni aiutanti di utilità rapida che utilizzano l'ES6 Import & Export standard che ho scritto che includono anche TypeScript. Forse posso fare in modo di rendere queste una rapida libreria che può essere installata nei progetti come dipendenza.

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

Dattiloscritto

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

promesse

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

16

Secondo http://youmightnotneedjquery.com/#ready è una buona sostituzione che funziona ancora con IE8

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

miglioramenti : Personalmente verificherei anche se il tipo di fnè una funzione. E come suggerito da @elliottregan, rimuovere il listener di eventi dopo l'uso.

Il motivo per cui rispondo tardi a questa domanda è perché stavo cercando questa risposta ma non sono riuscito a trovarla qui. E penso che questa sia la soluzione migliore.


1
Sì, questa è la risposta migliore secondo me. Facile da leggere ed esegue il codice anche se il DOM è già caricato. L'unica cosa che aggiungerei è rimuovere il listener di eventi dopo che l'evento è stato generato.
elliottregan,

14

Esiste una sostituzione basata su standard, DOMContentLoaded supportata da oltre il 90% + di browser, ma non da IE8 (quindi sotto l'utilizzo del codice da parte di JQuery per il supporto del browser) :

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

La funzione nativa di jQuery è molto più complicata del semplice window.onload, come illustrato di seguito.

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

1
Il nuovo jQuery ha eliminato il supporto per i browser più vecchi e ora hanno solo DOMContentLoadeded loadeventi in uso addEventListener, e prima di tutto il fuoco rimuove entrambi i listener, quindi non si attiva due volte.
jcubic,

8

In semplice JavaScript vaniglia, senza librerie? È un errore. $è semplicemente un identificatore e non è definito a meno che non venga definito.

jQuery definisce $come proprio "tutto l'oggetto" (noto anche come jQuerycosì puoi usarlo senza essere in conflitto con altre librerie). Se non stai usando jQuery (o qualche altra libreria che lo definisce), allora $non verrà definito.

Oppure stai chiedendo quale sia l'equivalente in JavaScript? In tal caso, probabilmente lo desideri window.onload, il che non è esattamente equivalente, ma è il modo più rapido e semplice per avvicinarti allo stesso effetto in JavaScript vaniglia.


39
Per i molti downvoter di questa risposta (e gli altri sotto): quando questa domanda è stata posta, diceva semplicemente: "Cosa è $ (documento). Già () in JavaScript? Non jquery. Che cos'è?" Sembrava che stesse chiedendo cosa significasse in JavaScript semplice vaniglia senza jQuery caricato. Nella mia risposta, ho tentato di rispondere a quella domanda, oltre a fornire la risposta più semplice per JavaScript semplice e senza jQuery o altre librerie nel caso fosse quello che intendeva. Si noti che tutto il contesto aggiuntivo è stato aggiunto da altre persone indovinando ciò che la domanda stava ponendo, non il poster originale.
Brian Campbell,

5

Il modo più semplice nei browser recenti sarebbe usare gli appropriati GlobalEventHandlers , onDOMContentLoaded , onload , onloadeddata (...)

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

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

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

L'evento DOMContentLoaded viene generato quando il documento HTML iniziale è stato completamente caricato e analizzato, senza attendere il completamento del caricamento di fogli di stile, immagini e sottoframe. Un carico di eventi molto diverso deve essere utilizzato solo per rilevare una pagina a pieno carico. È un errore incredibilmente popolare utilizzare il caricamento in cui DOMContentLoaded sarebbe molto più appropriato, quindi sii cauto.

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

La funzione utilizzata è un IIFE, molto utile in questo caso, poiché si attiva da solo quando è pronto:

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

È ovviamente più appropriato posizionarlo alla fine di qualsiasi script.

In ES6, possiamo anche scriverlo come una funzione freccia:

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

La cosa migliore è usare gli elementi DOM, possiamo aspettare che qualsiasi variabile sia pronta, che inneschi un IIFE con frecce.

Il comportamento sarà lo stesso, ma con un minore impatto sulla memoria.

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

In molti casi, l' oggetto documento si attiva anche quando è pronto , almeno nel mio browser. La sintassi è quindi molto bella, ma ha bisogno di ulteriori test sulla compatibilità.

document=(()=>{    /*Ready*/   })()

Potrebbe un trigger IIFE prima che il DOM abbia finito di caricare gli elementi dopo di esso?
CTS_AE,

Certo, è solo una funzione, una funzione anonima, in una chiusura.
NVRM,

0

Anche il body onLoad potrebbe essere un'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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.