Ok, questa potrebbe essere solo una domanda stupida, anche se sono sicuro che ci sono molte altre persone che fanno la stessa domanda di tanto in tanto. Io, voglio solo essere sicuro al 100% in ogni caso. Con jQuery conosciamo tutti il meraviglioso
$('document').ready(function(){});
Tuttavia, diciamo che voglio eseguire una funzione che è scritta in JavaScript standard senza alcuna libreria di supporto, e che voglio lanciare una funzione non appena la pagina è pronta a gestirla. Qual è il modo corretto di avvicinarsi a questo?
So che posso fare:
window.onload="myFunction()";
...o posso usare il tag body
:
<body onload="myFunction()">
...o posso anche provare in fondo alla pagina dopo tutto, ma alla fine body
o html
tag come:
<script type="text/javascript">
myFunction();
</script>
Qual è un metodo cross-browser (vecchio/nuovo) compatibile con l'emissione di una o più funzioni in un modo come jQuery's $.ready()
?
La cosa più semplice da fare in assenza di un framework che faccia tutta la compatibilità cross-browser per te è semplicemente mettere una chiamata al tuo codice alla fine del corpo. Questo è più veloce da eseguire di un gestore onload
perché questo aspetta solo che il DOM sia pronto, non che tutte le immagini vengano caricate. E questo funziona in ogni 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>
Per i browser moderni (qualsiasi cosa da IE9 in poi e qualsiasi versione di Chrome, Firefox o Safari), se volete essere in grado di implementare un metodo jQuery come $(document).ready()
che potete chiamare da qualsiasi luogo (senza preoccuparvi di dove sia posizionato lo script chiamante), potete semplicemente usare qualcosa come questo:
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);
}
}
Uso:
docReady(function() {
// DOM is loaded and ready for manipulation here
});
Se hai bisogno di piena compatibilità cross-browser (incluse le vecchie versioni di IE) e non vuoi aspettare il window.onload
, allora probabilmente dovresti andare a vedere come un framework come jQuery implementa il suo metodo $(document).ready()
. È abbastanza complicato a seconda delle capacità del browser.
Per darvi una piccola idea di cosa fa jQuery (che funzionerà ovunque sia posizionato il tag script).
Se supportato, prova lo standard:
document.addEventListener('DOMContentLoaded', fn, false);
con un fallback a:
window.addEventListener('load', fn, false )
o per le vecchie versioni di IE, usa:
document.attachEvent("onreadystatechange", fn);
con un fallback a:
window.attachEvent("onload", fn);
E, ci sono alcuni work-around nel percorso del codice di IE che non seguo bene, ma sembra che abbia qualcosa a che fare con i frame.
Qui c'è un sostituto completo di jQuery .ready()
scritto in semplice 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);
L'ultima versione del codice è condivisa pubblicamente su GitHub all'indirizzo https://github.com/jfriend00/docReady
Utilizzo:
// 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);
Questo è stato testato in:
lingua: lang-none -->
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
Implementazione di lavoro e banco di prova:
Ecco un riassunto di come funziona:
docReady(fn, context)
.docReady(fn, context)
viene chiamata, controlla se il gestore ready ha già sparato. Se è così, basta programmare il callback appena aggiunto per sparare subito dopo che questo thread di JS finisce con setTimeout(fn, 1)
.document.addEventListener
esiste, allora installa i gestori di eventi usando .addEventListener()
per entrambi gli eventi "DOMContentLoaded"
e "load"
. L'evento "load" è un evento di riserva per sicurezza e non dovrebbe essere necessario.document.addEventListener
non esiste, allora installa gestori di eventi usando .attachEvent()
per gli eventi "onreadystatechange"
e "onload"
.onreadystatechange
, controlla se il document.readyState === "complete"
e se è così, chiama una funzione per sparare tutti i gestori pronti.I gestori registrati con docReady()
sono garantiti per essere lanciati nell'ordine in cui sono stati registrati.
Se si chiama docReady(fn)
dopo che il documento è già pronto, il callback sarà programmato per essere eseguito non appena il thread di esecuzione corrente si concluderà usando setTimeout(fn, 1)
. Questo permette al codice chiamante di assumere sempre che siano callback asincroni che saranno chiamati più tardi, anche se più tardi è appena il thread corrente di JS finisce e conserva l'ordine di chiamata.
Il tuo metodo (mettere lo script prima del tag di chiusura del corpo)
<script>
myFunction()
</script>
</body>
</html>
è un modo affidabile per supportare i vecchi e i nuovi browser.