2431 Stimmen

$(document).ready entspricht ohne jQuery

Ich habe ein Skript, das Folgendes verwendet $(document).ready , aber es verwendet nichts anderes von jQuery. Ich möchte es durch Entfernen der jQuery-Abhängigkeit aufhellen.

Wie kann ich meine eigene $(document).ready Funktionalität ohne jQuery zu verwenden? Ich weiß, dass mit window.onload wird nicht dasselbe sein, da window.onload wird ausgelöst, nachdem alle Bilder, Rahmen usw. geladen wurden.

302 Stimmen

...und auch definitiv nicht die gleiche Funktionalität.

46 Stimmen

Als diese Antwort Staaten, wenn alles, was Sie von jQuery wollen, ist $(document).ready können Sie dieses Problem leicht lösen, indem Sie Ihren Code ganz unten auf der Seite ausführen, anstatt oben. HTML5Boilerplate verwendet genau diesen Ansatz.

5 Stimmen

Warum nicht einfach den DOMContentLoaded verwenden? Es ist IE9+ caniuse.com/domcontentloaded developer.mozilla.org/de-US/docs/Web/Events/DOMContentLoaded

0voto

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

0voto

Null Punkte 755

Die meisten Vanilla-JS-Ready-Funktionen berücksichtigen NICHT das Szenario, in dem die DOMContentLoaded Handler eingestellt ist nach das Dokument bereits geladen ist - das heißt, die Funktion wird nie laufen . Dies kann geschehen, wenn Sie nach DOMContentLoaded innerhalb einer async externes Skript ( <script async src="file.js"></script> ).

Der folgende Code prüft auf DOMContentLoaded nur, wenn das Dokument readyState ist nicht bereits interactive o complete .

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

Wenn Sie auch den IE unterstützen wollen:

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

0voto

Kithraya Punkte 318

Funktioniert in allen bekannten Browsern (getestet mit BrowserStack). IE6+, Safari 1+, Chrome 1+, Opera, etc. Verwendet DOMContentLoaded mit Rückgriff auf document.documentElement.doScroll() y window.onload .

/*! https://github.com/Kithraya/DOMContentLoaded v1.2.6 | MIT License */

DOMContentLoaded.version = "1.2.6";

function DOMContentLoaded() { "use strict";

    var ael = 'addEventListener', rel = 'removeEventListener', aev = 'attachEvent', dev = 'detachEvent';
    var alreadyRun = false, // for use in the idempotent function ready()
        funcs = arguments;

    // old versions of JS return '[object Object]' for null.
    function type(obj) { return (obj === null) ? 'null' : Object.prototype.toString.call(obj).slice(8,-1).toLowerCase() }
    function microtime() { return + new Date() } 

     /* document.readyState === 'complete' reports correctly in every browser I have tested, including IE.
        But IE6 to 10 don't return the correct readyState values as per the spec:
        readyState is sometimes 'interactive', even when the DOM isn't accessible in IE6/7 so checking for the onreadystatechange event like jQuery does is not optimal
        readyState is complete at basically the same time as 'window.onload' (they're functionally equivalent, within a few tenths of a second)
        Accessing undefined properties of a defined object (document) will not throw an error (in case readyState is undefined).
     */

    // Check for IE < 11 via conditional compilation
    /// values: 5?: IE5, 5.5?: IE5.5, 5.6/5.7: IE6/7, 5.8: IE8, 9: IE9, 10: IE10, 11*: (IE11 older doc mode), undefined: IE11 / NOT IE
    var jscript_version = Number( new Function("/*@cc_on return @_jscript_version; @*\/")() ) || NaN;

    // check if the DOM has already loaded
    if (document.readyState === 'complete') { ready(null); return; }  // here we send null as the readyTime, since we don't know when the DOM became ready.

    if (jscript_version < 9) { doIEScrollCheck(); return; } // For IE<9 poll document.documentElement.doScroll(), no further actions are needed.

     /* 
        Chrome, Edge, Firefox, IE9+, Opera 9+, Safari 3.1+, Android Webview, Chrome for Android, Edge Mobile, 
        Firefox for Android 4+, Opera for Android, iOS Safari, Samsung Internet, etc, support addEventListener
        And IE9+ supports 'DOMContentLoaded' 
     */

    if (document[ael]) {
        document[ael]("DOMContentLoaded", ready, false); 
        window[ael]("load", ready, false); // fallback to the load event in case addEventListener is supported, but not DOMContentLoaded
    } else 
    if (aev in window) { window[aev]('onload', ready);
        /* Old Opera has a default of window.attachEvent being falsy, so we use the in operator instead
           https://dev.opera.com/blog/window-event-attachevent-detachevent-script-onreadystatechange/

           Honestly if somebody is using a browser so outdated AND obscure (like Opera 7 where neither addEventListener 
           nor "DOMContLoaded" is supported, they deserve to wait for the full page).
           I CBA testing whether readyState === 'interactive' is truly interactive in browsers designed in 2003. I just assume it isn't (like in IE6-8). 
        */
    } else { // fallback to queue window.onload that will always work
       addOnload(ready);
    }

    // This function allows us to preserve any original window.onload handlers (in super old browsers where this is even necessary), 
    // while keeping the option to chain onloads, and dequeue them.

    function addOnload(fn) { var prev = window.onload; // old window.onload, which could be set by this function, or elsewhere

        // we add a function queue list to allow for dequeueing 
        // addOnload.queue is the queue of functions that we will run when when the DOM is ready
        if ( type( addOnload.queue ) !== 'array') { addOnload.queue = [];
            if ( type(prev) === 'function') { addOnload.queue.push( prev ); } // add the previously defined event handler
        }

        if (typeof fn === 'function') { addOnload.queue.push(fn) }

        window.onload = function() { // iterate through the queued functions
            for (var i = 0; i < addOnload.queue.length; i++) { addOnload.queue[i]() } 
        };
    }   

    // remove a queued window.onload function from the chain (simplified); 

    function dequeueOnload(fn) { var q = addOnload.queue, i = 0;

        // sort through the queued functions in addOnload.queue until we find `fn`
        if (type( q ) === 'array') {        // if found, remove from the queue
            for (; i < q.length; i++) { ;;(fn === q[i]) ? q.splice(i, 1) : 0; } // void( (fn === q[i]) ? q.splice(i, 1) : 0 ) 
        }
    }

    function ready(ev) { // idempotent event handler function
        if (alreadyRun) {return} alreadyRun = true; 

        // this time is when the DOM has loaded (or if all else fails, when it was actually possible to inference the DOM has loaded via a 'load' event)
        // perhaps this should be `null` if we have to inference readyTime via a 'load' event, but this functionality is better.
        var readyTime = microtime(); 

        detach(); // detach any event handlers

        // run the functions
        for (var i=0; i < funcs.length; i++) {  var func = funcs[i];

            if (type(func) === 'function') {
                func.call(document, { 'readyTime': (ev === null ? null : readyTime), 'funcExecuteTime': microtime() }, func); 
                // jquery calls 'ready' with `this` being set to document, so we'll do the same. 
            }       
        }
    }

    function detach() {
        if (document[rel]) { 
            document[rel]("DOMContentLoaded", ready); window[rel]("load", ready);
        } else
        if (dev in window) { window[dev]("onload", ready); } 
        else {
            dequeueOnload(ready);
        }                                                               
    }

    function doIEScrollCheck() { // for use in IE < 9 only.
        if ( window.frameElement ) { 
            // we're in an <iframe> or similar
            // the document.documentElemeent.doScroll technique does not work if we're not at the top-level (parent document)

            try { window.attachEvent("onload", ready); } catch (e) { } // attach to onload if were in an <iframe> in IE as there's no way to tell otherwise

            return;
        } 
        try {
            document.documentElement.doScroll('left');  // when this statement no longer throws, the DOM is accessible in old IE
        } catch(error) {
            setTimeout(function() {
                (document.readyState === 'complete') ? ready() : doIEScrollCheck();
            }, 50);
            return;
        }
        ready();
    }
}

Verwendung:

<script>
DOMContentLoaded(function(e) { console.log(e) });
</script>

-1voto

Whome Punkte 9949

Dies war eine gute https://stackoverflow.com/a/11810957/185565 die Lösung für den armen Mann. In einem Kommentar wurde ein Zähler für den Notausstieg erwogen. Dies ist meine Änderung.

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

-1voto

Forestrf Punkte 364

Edit des Edits von @duskwuff zur Unterstützung Internet Explorer 8 zu. Der Unterschied ist ein neuer Aufruf der Funktion test des regex und der setTimeout mit einer anonymen Funktion.

Außerdem habe ich den Timeout auf 99 gesetzt.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X