Oké, dit is misschien gewoon een domme vraag, hoewel ik er zeker van ben dat er genoeg andere mensen zijn die af en toe dezelfde vraag stellen. Ik, ik wil er gewoon 100% zeker van zijn, hoe dan ook. Met jQuery kennen we allemaal het prachtige
$('document').ready(function(){});
Maar laten's zeggen dat ik een functie wil uitvoeren die geschreven is in standaard JavaScript zonder dat er een bibliotheek achter zit, en dat ik een functie wil starten zodra de pagina klaar is om het aan te kunnen. Wat's de juiste manier om dit te benaderen?
Ik weet dat ik kan doen:
window.onload="myFunction()";
...of ik kan de body
tag gebruiken:
<body onload="myFunction()">
...of ik kan zelfs proberen onderaan de pagina na alles, maar het einde body
of html
tag zoals:
<script type="text/javascript">
myFunction();
</script>
Wat is een cross-browser(oud/nieuw)-conforme methode om een of meer functies uit te geven op een manier zoals jQuery's $.ready()
?
Het eenvoudigste om te doen bij gebrek aan een framework dat alle cross-browser compatibiliteit voor je doet is om gewoon een oproep naar je code aan het einde van de body te zetten. Dit is sneller uit te voeren dan een onload
handler omdat deze alleen wacht tot het DOM klaar is, niet tot alle afbeeldingen geladen zijn. En, dit werkt in elke browser.
<!doctype html>
<html>
<head>
</head>
<body>
Your HTML here
<script>
// self executing function here
(function() {
// your page initialization code here
// the DOM will be available here
})();
</script>
</body>
</html>
Voor moderne browsers (alles vanaf IE9 en nieuwer en elke versie van Chrome, Firefox of Safari), als je in staat wilt zijn om een jQuery-achtige $(document).ready()
methode te implementeren die je overal vandaan kunt aanroepen (zonder je zorgen te maken over waar het aanroepende script is gepositioneerd), kun je gewoon iets als dit gebruiken:
function docReady(fn) {
// see if DOM is already available
if (document.readyState === "complete" || document.readyState === "interactive") {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
Gebruik:
docReady(function() {
// DOM is loaded and ready for manipulation here
});
Als je volledige cross browser compatibiliteit nodig hebt (inclusief oude versies van IE) en je wilt niet wachten op window.onload
, dan moet je waarschijnlijk gaan kijken naar hoe een framework als jQuery zijn $(document).ready()
methode implementeert. Het is vrij ingewikkeld, afhankelijk van de mogelijkheden van de browser.
Om je een beetje een idee te geven wat jQuery doet (wat overal zal werken waar de script tag is geplaatst).
Indien ondersteund, probeert het de standaard:
document.addEventListener('DOMContentLoaded', fn, false);
met een fallback naar:
window.addEventListener('load', fn, false )
of voor oudere versies van IE, gebruikt het:
document.attachEvent("onreadystatechange", fn);
met een fallback naar:
window.attachEvent("onload", fn);
En, er zijn wat work-arounds in het IE code pad dat ik niet helemaal volg, maar het lijkt erop dat het iets te maken heeft met frames.
Hier is een volledige vervanger voor jQuery's .ready()
geschreven in gewoon javascript:
(function(funcName, baseObj) {
// The public function name defaults to window.docReady
// but you can pass in your own object and own function name and those will be used
// if you want to put them in a different namespace
funcName = funcName || "docReady";
baseObj = baseObj || window;
var readyList = [];
var readyFired = false;
var readyEventHandlersInstalled = false;
// call this when the document is ready
// this function protects itself against being called more than once
function ready() {
if (!readyFired) {
// this must be set to true before we start calling callbacks
readyFired = true;
for (var i = 0; i < readyList.length; i++) {
// if a callback here happens to add new ready handlers,
// the docReady() function will see that it already fired
// and will schedule the callback to run right after
// this event loop finishes so all handlers will still execute
// in order and no new ones will be added to the readyList
// while we are processing the list
readyList[i].fn.call(window, readyList[i].ctx);
}
// allow any closures held by these functions to free
readyList = [];
}
}
function readyStateChange() {
if ( document.readyState === "complete" ) {
ready();
}
}
// This is the one public interface
// docReady(fn, context);
// the context argument is optional - if present, it will be passed
// as an argument to the callback
baseObj[funcName] = function(callback, context) {
if (typeof callback !== "function") {
throw new TypeError("callback for docReady(fn) must be a function");
}
// if ready has already fired, then just schedule the callback
// to fire asynchronously, but right away
if (readyFired) {
setTimeout(function() {callback(context);}, 1);
return;
} else {
// add the function and context to the list
readyList.push({fn: callback, ctx: context});
}
// if document already ready to go, schedule the ready function to run
if (document.readyState === "complete") {
setTimeout(ready, 1);
} else if (!readyEventHandlersInstalled) {
// otherwise if we don't have event handlers installed, install them
if (document.addEventListener) {
// first choice is DOMContentLoaded event
document.addEventListener("DOMContentLoaded", ready, false);
// backup is window load event
window.addEventListener("load", ready, false);
} else {
// must be IE
document.attachEvent("onreadystatechange", readyStateChange);
window.attachEvent("onload", ready);
}
readyEventHandlersInstalled = true;
}
}
})("docReady", window);
De laatste versie van de code is publiekelijk gedeeld op GitHub op https://github.com/jfriend00/docReady
Gebruik:
// pass a function reference
docReady(fn);
// use an anonymous function
docReady(function() {
// code here
});
// pass a function reference and a context
// the context will be passed to the function as the first argument
docReady(fn, context);
// use an anonymous function with a context
docReady(function(context) {
// code here that can use the context argument that was passed to docReady
}, ctx);
Dit is getest in:
IE6 and up
Firefox 3.6 and up
Chrome 14 and up
Safari 5.1 and up
Opera 11.6 and up
Multiple iOS devices
Multiple Android devices
Werkende implementatie en testbed:
Hier's een samenvatting van hoe het werkt:
docReady(fn, context)
.docReady(fn, context)
wordt aangeroepen, controleer dan of de ready handler al gevuurd heeft. Als dat zo is, plan dan de nieuw toegevoegde callback om te vuren direct nadat deze thread van JS is afgelopen met setTimeout(fn, 1)
.document.addEventListener
bestaat, installeer dan event handlers met .addEventListener()
voor zowel "DOMContentLoaded"
als "load"
events. De `"load" is een backup event voor de veiligheid en zou niet nodig moeten zijn.document.addEventListener
niet bestaat', installeer dan event handlers met behulp van
.attachEvent()voor
"onreadystatechange"en
"onload"` events.onreadystatechange
gebeurtenis, controleer of de document.readyState === "complete"
en zo ja, roep een functie aan om alle ready handlers af te vuren.Handlers geregistreerd met docReady()
worden gegarandeerd uitgevoerd in de volgorde waarin ze zijn geregistreerd.
Als je docReady(fn)
aanroept nadat het document al klaar is, zal de callback gepland worden om uit te voeren zodra de huidige thread van uitvoering is voltooid met setTimeout(fn, 1)
. Hierdoor kan de aanroepende code altijd aannemen dat het async callbacks zijn die later worden aangeroepen, zelfs als later is zodra de huidige thread van JS is afgelopen en het behoudt de volgorde van aanroepen.
Uw methode (script plaatsen voor de afsluitende body tag)
<script>
myFunction()
</script>
</body>
</html>
is een betrouwbare manier om oude en nieuwe browsers te ondersteunen.