Okei, tämä saattaa olla vain typerä kysymys, vaikka olen varma, että monet muut ihmiset kysyvät samaa kysymystä aika ajoin. Itse haluan vain olla 100% varma asiasta kumminkin. JQueryn kanssa me kaikki tiedämme ihanan
$('document').ready(function(){});
Sanotaan kuitenkin, että haluan ajaa funktiota, joka on kirjoitettu tavallisella JavaScriptillä ilman kirjastoa sen tukena, ja että haluan käynnistää funktion heti, kun sivu on valmis käsittelemään sitä. Mikä'on oikea tapa lähestyä tätä?
Tiedän, että voin tehdä näin:
window.onload="myFunction()";
...tai voin käyttää body
-tagia:
<body onload="myFunction()">
...tai voin jopa kokeilla sivun alareunassa kaiken jälkeen, mutta body
- tai html
-tunnisteen lopussa, kuten:
<script type="text/javascript">
myFunction();
</script>
Mikä on selainten(vanha/uusi)-yhteensopiva tapa antaa yksi tai useampi funktio jQueryn tapaan $.ready()
?
Yksinkertaisinta on vain laittaa kutsu koodiin rungon loppuun, jos ei ole olemassa kehystä, joka huolehtii selaintenvälisestä yhteensopivuudesta puolestasi. Tämä on nopeampi toteuttaa kuin onload
-käsittelijä, koska tämä odottaa vain DOM:n olevan valmis, ei kaikkien kuvien latautumista. Ja tämä toimii kaikissa selaimissa.
<!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>
Nykyaikaisissa selaimissa (kaikki IE9:stä ja uudemmista sekä kaikki Chromen, Firefoxin tai Safarin versiot), jos haluat toteuttaa jQueryn kaltaisen $(document).ready()
-metodin, jota voit kutsua mistä tahansa (huolehtimatta siitä, missä kutsuva skripti on sijoitettu), voit käyttää jotakin tämän kaltaista:
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);
}
}
Käyttö:
docReady(function() {
// DOM is loaded and ready for manipulation here
});
Jos tarvitset täydellistä selainten välistä yhteensopivuutta (mukaan lukien IE:n vanhat versiot) etkä halua odottaa window.onload
-menetelmää, sinun kannattaa todennäköisesti katsoa, miten jQueryn kaltainen kehys toteuttaa $(document).ready()
-metodinsa. Se on melko monimutkaista selaimen ominaisuuksista riippuen.
Annan sinulle pienen käsityksen siitä, mitä jQuery tekee (joka toimii missä tahansa script-tagi on sijoitettu).
Jos se on tuettu, se kokeilee standardia:
document.addEventListener('DOMContentLoaded', fn, false);
ja varasuunnitelmana on:
window.addEventListener('load', fn, false )
tai IE:n vanhemmissa versioissa se käyttää:
document.attachEvent("onreadystatechange", fn);
ja varajärjestelmä on:
window.attachEvent("onload", fn);
Ja IE:n koodipolussa on joitakin kiertoteitä, joita en oikein ymmärrä, mutta näyttää siltä, että se liittyy jotenkin kehyksiin.
Tässä on jQueryn täydellinen korvike .ready()
, joka on kirjoitettu tavallisella javascriptillä:
(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);
Koodin uusin versio on jaettu julkisesti GitHubissa osoitteessa https://github.com/jfriend00/docReady.
Käyttö:
// 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);
Tämä on testattu:
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
Toimiva toteutus ja testausympäristö:
Tässä on yhteenveto siitä, miten se toimii:
docReady(fn, context)
.docReady(fn, context)
kutsutaan, tarkista, onko valmis käsittelijä jo lauennut. Jos on, ajoita juuri lisätty takaisinkutsu laukeamaan heti sen jälkeen, kun tämä JS-säie on päättynyt, komennolla setTimeout(fn, 1)
.document.addEventListener
on olemassa, asenna tapahtumakäsittelijät käyttämällä .addEventListener()
sekä "DOMContentLoaded"
- että "load"
-tapahtumille. "load" on varmuuden vuoksi varatapahtuma, eikä sitä pitäisi tarvita.document.addEventListener
ei ole olemassa, asenna tapahtumankäsittelijät käyttäen .attachEvent()
tapahtumille "onreadystatechange"
ja "onload"
.onreadystatechange
-tapahtumassa, onko document.readyState === "complete"
, ja jos on, kutsu funktiota, joka käynnistää kaikki ready-käsittelijät.docReady()
:lla rekisteröidyt käsittelijät aktivoidaan taatusti siinä järjestyksessä kuin ne on rekisteröity.
Jos kutsut docReady(fn)
sen jälkeen, kun dokumentti on jo valmis, takaisinkutsu ajoitetaan suoritettavaksi heti, kun nykyinen suoritussäie päättyy setTimeout(fn, 1)
:n avulla. Näin kutsuva koodi voi aina olettaa, että kyseessä ovat asynkroniset takaisinkutsut, joita kutsutaan myöhemmin, vaikka "myöhemmin" olisikin heti, kun nykyinen JS-säie päättyy, ja se säilyttää kutsujärjestyksen.
Menetelmäsi (komentosarjan sijoittaminen ennen sulkevaa body-tagia)
<script>
myFunction()
</script>
</body>
</html>
on luotettava tapa tukea vanhoja ja uusia selaimia.