javascript vanilla - $(document).ready équivalent sans jQuery




js dom (25)

Edit of the edit of @duskwuff to support Internet Explorer 8 too. The difference is a new call to the function test of the regex and the setTimeout with an anonymous function.

Also, I set the timeout to 99.

function ready(f){/in/.test(document.readyState)?setTimeout(function(){ready(f);},99):f();}

J'ai un script qui utilise $(document).ready , mais il n'utilise rien d'autre de jQuery. Je voudrais l'alléger en supprimant la dépendance jQuery.

Comment puis-je implémenter ma propre fonctionnalité $(document).ready sans utiliser jQuery? Je sais que l'utilisation de window.onload ne sera pas la même, car window.onload déclenchera après le window.onload de toutes les images, cadres, etc.


Je l'utilisais récemment pour un site mobile. Ceci est la version simplifiée de John Resig de "Pro JavaScript Techniques". Cela dépend 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;
})();

This was a good https://.com/a/11810957/185565 poor man's solution. One comment considered a counter to bail out in case of emergency. This is my modification.

function doTheMagic(counter) {
  alert("It worked on " + counter);
}

// wait for document ready then call handler function
var checkLoad = function(counter) {
  counter++;
  if (document.readyState != "complete" && counter<1000) {
    var fn = function() { checkLoad(counter); };
    setTimeout(fn,10);
  } else doTheMagic(counter);
};
checkLoad(0);

If you don't have to support very old browsers, here is a way to do it even when your external script is loaded with async attribute:

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

Trois options:

  1. Si le script est la dernière balise du corps, le DOM sera prêt avant l'exécution de la balise de script
  2. Lorsque le DOM est prêt, "readyState" devient "complete"
  3. Tout mettre sous l'écouteur d'événement 'DOMContentLoaded'

onreadystatechange

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

Source: MDN

DOMContentLoaded

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

Préoccupé par les navigateurs de l'âge de pierre: Allez au code source jQuery et utilisez la fonction ready . Dans ce cas, vous n'êtes pas en train d'analyser + en exécutant toute la bibliothèque dont vous ne faites qu'une toute petite partie.


Nous avons trouvé une implémentation cross-browser rapide et sale qui pourrait faire l'affaire pour les cas les plus simples avec une implémentation minimale:

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

Ce code croisé appellera une fonction une fois que le DOM sera prêt:

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

Voici comment cela fonctionne:

  1. La première ligne de domReady appelle la méthode toString de la fonction pour obtenir une représentation sous forme de chaîne de la fonction que vous transmettez et l'enveloppe dans une expression qui appelle immédiatement la fonction.
  2. Le reste de domReady crée un élément de script avec l'expression et l'ajoute au body du document.
  3. Le navigateur exécute des balises de script ajoutées au body après que le DOM est prêt.

Par exemple, si vous faites ceci: domReady(function(){alert();}); , ce qui suit sera ajouté à l'élément body :

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

Notez que cela ne fonctionne que pour les fonctions définies par l'utilisateur. Ce qui suit ne fonctionnera pas: domReady(alert);


La fonction prête dans jQuery fait un certain nombre de choses. Franchement, je ne vois pas l'intérêt de le remplacer à moins que vous ayez une sortie incroyablement petite de votre site web. jQuery est une bibliothèque minuscule, et il gère toutes sortes de choses que vous aurez besoin plus tard.

Quoi qu'il en soit, il est bindReady le bindReady ici, ouvrez jQuery et regardez la méthode bindReady .

It starts by calling either document.addEventListener("DOMContentLoaded") or document.attachEvent('onreadystatechange') depending on the event model, and goes on from there.


Les solutions setTimeout / setInterval présentées ici ne fonctionneront que dans des circonstances spécifiques.

Le problème apparaît en particulier dans les anciennes versions d'Internet Explorer jusqu'à 8.

Les variables affectant le succès de ces solutions setTimeout / setInterval sont:

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

le code original (Javascript natif) résolvant ce problème spécifique est ici:

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

c'est le code à partir duquel l'équipe jQuery a construit son implémentation.


Modifier:

Voici un remplacement viable pour jQuery prêt

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

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

Comme la réponse acceptée était très loin d'être complète, j'ai assemblé une fonction "prête" comme jQuery.ready() basée sur jQuery 1.6.2 source:

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

Comment utiliser:

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

Je ne suis pas sûr de la fonctionnalité de ce code, mais cela a bien fonctionné avec mes tests superficiels. Cela a pris du temps, alors j'espère que vous et les autres pourrez en bénéficier.

PS: Je suggère de le compiling .

Ou vous pouvez utiliser http://dustindiaz.com/smallest-domready-ever :

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

ou la fonction native si vous avez seulement besoin de supporter les nouveaux navigateurs (Contrairement à jQuery ready, ceci ne fonctionnera pas si vous ajoutez ceci après le chargement de la page)

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

Cette question a été posée il y a très longtemps. Pour tous ceux qui voient juste cette question, il y a maintenant un site appelé "vous ne pourriez pas avoir besoin de jquery" qui décompose - par le niveau de support IE requis - toutes les fonctionnalités de jquery et fournit des bibliothèques alternatives plus petites.

IE8 document script prêt selon vous pourrait ne pas besoin de 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();
        });
}

If you are loading jQuery near the bottom of BODY, but are having trouble with code that writes out jQuery(<func>) or jQuery(document).ready(<func>), check out jqShim on Github.

Rather than recreate its own document ready function, it simply holds onto the functions until jQuery is available then proceeds with jQuery as expected. The point of moving jQuery to the bottom of body is to speed up page load, and you can still accomplish it by inlining the jqShim.min.js in the head of your template.

I ended up writing this code to make moving all the scripts in WordPress to the footer, and just this shim code now sits directly in the header.


In short, instead of the $(document).ready() used in jQuery, we can use a JavaScript method:

<script>
    document.addEventListener("DOMContentLoaded", function_name, false);
    function function_name(){
        statements;
    }
</script>

Thus, when the page is ready ie DOMContentLoaded only then the function function_name() will be invoked.


La solution de l'homme pauvre:

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

checkLoad();  

Voir le violon

Ajouté celui-ci, un peu mieux je suppose, propre portée, et non récursif

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

Voir le violon


J'utilise ceci:

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

Note: Cela ne fonctionne probablement qu'avec les nouveaux navigateurs, en particulier ceux-ci: http://caniuse.com/#feat=domcontentloaded


Il est toujours bon d'utiliser des équivalents JavaScript par rapport à jQuery. Une des raisons est une bibliothèque de moins à dépendre et ils sont beaucoup plus rapides que les équivalents jQuery.

Une référence fantastique pour les équivalents jQuery est http://youmightnotneedjquery.com/ .

En ce qui concerne votre question, j'ai pris le code ci-dessous à partir du lien ci-dessus :) Seul bémol est-il fonctionne uniquement avec Internet Explorer 9+ et plus tard.

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

This approach is the shortest way I can think of.

The solution based on the DOMContentLoaded event only works if the script is loaded before the document, whereas the lazy check suggested here ensures the code is executed always, even in scripts loaded dynamically later on, exactly as the JQuery's document ready.

This code is compatible with all browsers (including some legacy, down to IE6 and Safari for Windows).

(function ready() {
    if (!document.body) {setTimeout(ready, 50); return;}
    // Document is ready here
})();

Il est intéressant de regarder dans Rock Solid addEvent () et http://www.braksator.com/how-to-make-your-own-jquery .

Voici le code au cas où le site tombe en panne

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

Ajoutez simplement ceci au bas de votre page HTML ...

<script>
    Your_Function();
</script>

Parce que, les documents HTML sont analysés par haut-bas.


Placez votre <script>/*JavaScript code*/</script> juste avant la </body> fermeture </body> .

Certes, cela peut ne pas convenir aux besoins de tout le monde car il faut changer le fichier HTML plutôt que de simplement faire quelque chose dans le fichier JavaScript a la document.ready , mais quand même ...


Que diriez-vous de cette solution?

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

Voici ce que j'utilise, c'est rapide et couvre toutes les bases je pense; fonctionne pour tout sauf IE <9.

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

Cela semble capturer tous les cas:

  • se déclenche immédiatement si le DOM est déjà prêt (si le DOM n'est pas en train de "charger" mais "interactif" ou "complet")
  • si le DOM est encore en train de charger, il configure un écouteur d'événement pour quand le DOM est disponible (interactif).

L'événement DOMContentLoaded est disponible dans IE9 et tout le reste, donc je pense personnellement que c'est OK pour l'utiliser. Réécrivez la déclaration de fonction de flèche à une fonction anonyme régulière si vous ne transpilez pas votre code de ES2015 à ES5.

Si vous voulez attendre que tous les éléments soient chargés, toutes les images affichées, etc., utilisez plutôt window.onload.


For IE9+:

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

function onDocReady(fn){
    (function c(){document.readyState!=="loading"?fn():setTimeout(c,9)})();
}   

function onDocLoad(fn){
    (function c(){document.readyState==="complete"?fn():setTimeout(c,30)})();
}    

onDocReady provides a callback when the HTML dom is ready to fully access/parse/manipulate.

onDocLoad provides a callback when everything has loaded (images etc)

  • These functions can be called whenever you want.
  • Supports multiple "listeners".
  • Will work in any browser.

jQuery: vous pensez beaucoup à 'interroger le DOM ' pour les éléments DOM et à faire quelque chose.

AngularJS: LE modèle est la vérité et vous pensez toujours de cet angle.

Par exemple, lorsque vous obtenez des données du serveur que vous souhaitez afficher sous un format quelconque dans le DOM, dans jQuery, vous devez "1. FIND 'où vous voulez placer ces données dans le DOM, le' 2. UPDATE / APPEND 'en créant un nouveau nœud ou en définissant simplement son innerHTML . Ensuite, lorsque vous souhaitez mettre à jour cette vue, vous passez à «3. TROUVEZ 'l'emplacement et' 4. METTRE À JOUR'. Ce cycle de recherche et de mise à jour est effectué dans le même contexte d’obtention et de formatage des données du serveur dans AngularJS.

Avec AngularJS, vous avez votre modèle (les objets JavaScript auxquels vous êtes déjà habitué) et la valeur du modèle vous renseigne sur le modèle (évidemment) et sur la vue. Une opération sur le modèle se propage automatiquement à la vue. Je n'ai pas à y penser. Vous vous retrouverez dans AngularJS, vous ne trouvez plus rien dans le DOM.

Autrement dit, dans jQuery, vous devez penser aux sélecteurs CSS, c’est-à-dire où est le divou tdqui a une classe ou un attribut, etc., afin que je puisse obtenir leur code HTML, leur couleur ou leur valeur, mais dans AngularJS, vous vous retrouverez à penser comme ceci: quel modèle suis-je en train de traiter? Je vais définir la valeur du modèle sur true. Vous ne vous souciez pas de savoir si la vue reflétant cette valeur est une case à cocher ou réside dans un tdélément (détails auxquels vous auriez souvent eu besoin de penser dans jQuery).

Et avec la manipulation DOM dans AngularJS, vous vous retrouvez en train d'ajouter des directives et des filtres, que vous pouvez considérer comme des extensions HTML valides.

Une dernière chose que vous allez expérimenter dans AngularJS: dans jQuery, vous appelez souvent les fonctions jQuery, dans AngularJS, AngularJS appelle vos fonctions, de sorte que AngularJS "vous explique comment faire les choses", mais que les avantages en valent la peine. signifie généralement apprendre ce que veut AngularJS ou la manière dont AngularJS exige que vous présentiez vos fonctions et il l'appellera en conséquence. C’est l’une des choses qui fait d’AngularJS un cadre plutôt qu’une bibliothèque.







javascript jquery