Quel est l'équivalent non jQuery de '$ (document) .ready ()'?

444

Quel est l'équivalent non jQuery de $(document).ready()?

TIMEX
la source
4
Si vous souhaitez reproduire l' $(document).ready()événement jQuery sans utiliser de bibliothèque, jetez un œil à ceci: stackoverflow.com/questions/1795089/…
CMS
@OP: consultez la page 89 de Pro JavaScript Techniques pour une implémentation vanilla JavaScript de $(document).ready()- books.google.com/… . Il utilise également l' addEventabstraction de liaison d'événement écrite par Dean Edwards, dont le code est également dans le livre :)
Russ Cam
2
doublon possible de $ (document) .équivalent déjà sans jQuery
Qantas 94 Heavy

Réponses:

73

Ce $(document).ready()qui est bien, c'est qu'il se déclenche avant window.onload. La fonction de chargement attend que tout soit chargé, y compris les ressources externes et les images. $(document).ready, cependant, se déclenche lorsque l'arborescence DOM est terminée et peut être manipulée. Si vous voulez rendre DOM prêt, sans jQuery, vous pouvez vous connecter à cette bibliothèque. Quelqu'un a extrait juste la readypartie de jQuery. C'est joli et petit et vous pourriez le trouver utile:

domready chez Google Code

Doug Neiner
la source
4
Réseau de codes DomReady! via @CMS sur github: github.com/cms/domready/network
Kzqai
45
Cela ne répond pas à la question et ne montre aucun code non jQuery. Comment at-il obtenu autant de votes positifs?
Daniel W.
3
@DanielW. Parce que c'est simple et pratique. La plupart d'entre nous sommes venus ici à la recherche d'un moyen de s'assurer que DOM est prêt à être utilisé par le code javascript.
abarazal
Oui, mais certains d'entre nous sont venus ici pour une réponse réelle.
Slbox
615

Cela fonctionne parfaitement, de l'ECMA

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

Le window.onloadn'est pas égal à JQuery $(document).readycar $(document).readyn'attend que l'arborescence DOM tout en window.onloadvérifiant tous les éléments, y compris les ressources externes et les images.

EDIT : ajout d'IE8 et d'un équivalent plus ancien, grâce à l' observation de Jan Derk . Vous pouvez lire la source de ce code sur MDN à ce lien :

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

Il existe d'autres options en dehors de "interactive". Voir le lien MDN pour plus de détails.

sospedra
la source
D'accord avec Benjamin. Vous ne pouvez pas simplement utiliser attachEvent. Par exemple, dans Chrome, vous obtenez: Uncaught TypeError: document.attachEvent n'est pas une fonction. Utilisez la réponse liée de Jan Derk.
Manuel Arwed Schmidt
9
Et si le document était déjà chargé lors de l'appel de ce script? Rien ne se passera du tout :(
oriadam
8
@Deerloper Nope, viens de l'essayer sur la console Chrome - rien ne s'est passé: document.addEventListener("DOMContentLoaded",function(){console.log(123)})essayez-le maintenant
oriadam
2
Prise en charge de DOMContentLoaded dans les navigateurs: caniuse.com/domcontentloaded
Guillaume Husta
1
@elliottregan c'est vrai je retire le commentaire pour éviter de polluer ce fil je vous conseille tous de faire de même :) Et laissez un commentaire si besoin en faisant remarquer le commentaire si besoin. Puisque c'est un supplément car cela va au-delà des questions d'OC
sospedra
43

Une petite chose que j'ai mise en place

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

Comment l'utiliser

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

Vous pouvez également modifier le contexte dans lequel le rappel s'exécute en passant un deuxième argument

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

domReady(init, console);
Je vous remercie
la source
2
Je vous remercie. J'aime le fait qu'il soit rétrocompatible. Aller de l'avant ne signifie pas simplement laisser des gens moins fortunés derrière. Ne pas pouvoir utiliser un navigateur moderne (pour quelque raison que ce soit) est malheureux ...
CO
28

Maintenant que nous sommes en 2018, voici une méthode rapide et simple.

Cela ajoutera un écouteur d'événements, mais s'il s'est déjà déclenché, nous vérifierons que le dom est dans un état prêt ou qu'il est complet. Cela peut se déclencher avant ou après le chargement des sous-ressources (images, feuilles de style, cadres, 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!"));

Lectures supplémentaires


Mise à jour

Voici quelques aides utilitaires rapides utilisant l'importation et l'exportation standard ES6 que j'ai écrites qui incluent également TypeScript. Peut-être que je peux me débrouiller pour en faire une bibliothèque rapide qui peut être installée dans des projets en tant que dépendance.

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

Manuscrit

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

Promesses

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
la source
16

Selon http://youmightnotneedjquery.com/#ready, un bon remplacement qui fonctionne toujours avec IE8 est

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

améliorations : Personnellement, je vérifierais également si le type de fnest une fonction. Et comme @elliottregan suggéré de supprimer l'écouteur d'événements après utilisation.

La raison pour laquelle je réponds à cette question tardivement est que je cherchais cette réponse mais que je ne l'ai pas trouvée ici. Et je pense que c'est la meilleure solution.

en ligne Thomas
la source
1
Oui, c'est la meilleure réponse à mon avis. Facile à lire, il exécute le code même si le DOM est déjà chargé. La seule chose que j'ajouterais est de supprimer l'écouteur d'événements après le déclenchement de l'événement.
elliottregan
14

Il existe un remplacement basé sur des normes, DOMContentLoaded qui est pris en charge par plus de 90% + des navigateurs, mais pas IE8 (Donc, ci-dessous, l'utilisation du code par JQuery pour la prise en charge du navigateur) :

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

La fonction native de jQuery est beaucoup plus compliquée que simplement window.onload, comme illustré ci-dessous.

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
la source
1
Le nouveau jQuery a supprimé la prise en charge des anciens navigateurs et maintenant ils ne disposent DOMContentLoadedque des loadévénements addEventListeneret, en premier lieu, ce feu supprime les deux écouteurs, de sorte qu'il ne se déclenche pas deux fois.
jcubic
8

En JavaScript simple vanille, sans bibliothèques? C'est une erreur.$est simplement un identifiant et n'est pas défini, sauf si vous le définissez.

jQuery définit $comme son propre "tout objet" (également connu sous le nom jQueryafin que vous puissiez l'utiliser sans entrer en conflit avec d'autres bibliothèques). Si vous n'utilisez pas jQuery (ou une autre bibliothèque qui le définit), alors $ne sera pas défini.

Ou demandez-vous quel est l'équivalent en JavaScript simple? Dans ce cas, vous voulez probablement window.onload, ce qui n'est pas exactement équivalent, mais c'est le moyen le plus rapide et le plus simple de se rapprocher du même effet en JavaScript vanille.

Brian Campbell
la source
39
Pour les nombreux downvoters de cette réponse (et les autres ci-dessous): lorsque cette question a été posée, elle disait simplement: "Qu'est-ce que $ (document) .ready () en javascript? Pas jquery. Qu'est-ce que c'est?" On aurait dit qu'il demandait ce que cela signifiait en JavaScript vanille simple sans jQuery chargé. Dans ma réponse, j'ai essayé de répondre à cette question, ainsi que de donner la réponse facile la plus proche pour JavaScript simple-vanilla sans jQuery ou d'autres bibliothèques au cas où c'est ce qu'il voulait dire. Notez que tout le contexte supplémentaire a été ajouté par d'autres personnes devinant ce que la question demandait, pas l'affiche originale.
Brian Campbell
5

Le moyen le plus simple dans les navigateurs récents serait d'utiliser les GlobalEventHandlers appropriés , onDOMContentLoaded , onload , onloadeddata (...)

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

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

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

L'événement DOMContentLoaded est déclenché lorsque le document HTML initial a été complètement chargé et analysé, sans attendre la fin du chargement des feuilles de style, des images et des sous-trames. Un chargement d'événement très différent ne doit être utilisé que pour détecter une page entièrement chargée. C'est une erreur incroyablement populaire d'utiliser la charge là où DOMContentLoaded serait beaucoup plus approprié, alors soyez prudent.

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

La fonction utilisée est une IIFE, très utile dans ce cas, car elle se déclenche lorsqu'elle est prête:

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

Il est évidemment plus approprié de le placer à la fin de tout script.

Dans ES6, nous pouvons également l'écrire comme une fonction de flèche:

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

Le mieux est d'utiliser les éléments DOM, on peut attendre que n'importe quelle variable soit prête, ce qui déclenche un IIFE fléché.

Le comportement sera le même, mais avec moins d'impact sur la mémoire.

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

Dans de nombreux cas, l' objet document se déclenche également lorsqu'il est prêt , au moins dans mon navigateur. La syntaxe est alors très agréable, mais elle nécessite des tests supplémentaires sur les compatibilités.

document=(()=>{    /*Ready*/   })()
NVRM
la source
Un IIFE pourrait-il se déclencher avant que le DOM ait fini de charger des éléments après lui?
CTS_AE
Bien sûr, c'est juste une fonction, une fonction anonyme, dans une fermeture.
NVRM
0

Le corps onLoad pourrait également être une alternative:

<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
la source