Ok, esta pode ser apenas uma pergunta tola, embora I'tenho certeza que há muitas outras pessoas fazendo a mesma pergunta de vez em quando. Eu, só quero ter 100% de certeza sobre isso de qualquer maneira. Com jQuery todos nós conhecemos a maravilhosa
$('document').ready(function(){});
No entanto, deixemos's dizer que eu quero executar uma função que está escrita em JavaScript padrão sem o suporte de biblioteca, e que eu quero lançar uma função assim que a página estiver pronta para lidar com ela. Qual'é a maneira adequada de abordar isto?
Eu sei que posso fazer:
window.onload="myFunction()";
...ou posso usar a etiqueta "corpo":
<body onload="myFunction()">
...ou eu posso até tentar no final da página depois de tudo, mas o final body
ou html
tag like:
<script type="text/javascript">
myFunction();
</script>
O que é um método compatível com o cross-browser(velho/novo) para emitir uma ou mais funções de uma maneira como jQuery's $.ready()
?
A coisa mais simples a fazer na ausência de uma estrutura que faça toda a compatibilidade entre navegadores para você é apenas colocar uma chamada para o seu código no final do corpo. Isto é mais rápido de executar do que um manipulador `onload' porque isto espera apenas que o DOM esteja pronto, não que todas as imagens sejam carregadas. E, isto funciona em todos os navegadores.
<!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>
Para navegadores modernos (qualquer coisa do IE9 e mais recentes e qualquer versão do Chrome, Firefox ou Safari), se você quiser ser capaz de implementar um método jQuery como $(document).ready()
que você pode chamar de qualquer lugar (sem se preocupar com onde o script de chamada está posicionado), você pode simplesmente utilizar algo como isto:
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 você precisa de compatibilidade cruzada total (incluindo versões antigas do IE) e não quer esperar pelo window.onload', então você provavelmente deveria ir ver como um framework como o jQuery implementa seu método
$(document).ready()`. Ele está bastante envolvido, dependendo das capacidades do navegador.
Para lhe dar uma pequena ideia do que jQuery faz (que irá funcionar onde quer que a etiqueta do script seja colocada).
Se suportado, ele tenta o padrão:
document.addEventListener('DOMContentLoaded', fn, false);
com um recuo para:
window.addEventListener('load', fn, false )
ou para versões mais antigas do IE, ele usa:
document.attachEvent("onreadystatechange", fn);
com um recuo para:
window.attachEvent("onload", fn);
E, há algumas soluções no caminho do código IE que eu não sigo, mas parece que tem algo a ver com molduras.
Aqui está um substituto completo para jQuery's .ready()
escrito em javascript simples:
(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);
A última versão do código é compartilhada publicamente no GitHub em https://github.com/jfriend00/docReady.
Uso:
// 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);
Isto já foi testado:
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
Implementação de trabalho e banco de ensaio:
Aqui está um resumo de como funciona:
docReady(fn, contexto)
.docReady(fn, contexto)
for chamado, verifique se o manipulador pronto já disparou. Se assim for, agende a nova chamada de retorno para disparar logo após esta linha do JS terminar com setTimeout(fn, 1)
.document.addEventListener
existe, então instale os manipuladores de eventos utilizando .addEventListener()
para ambos os eventos "DOMContentLoaded"
e "load"
. O "load" é um evento de backup para segurança e não deve ser necessário.document.addEventListener' não existir, então instale manipuladores de eventos utilizando
.attachEvent()para
"onreadystatechange"e
"onload"` eventos.onreadystatechange
, verifique se o document.readyState === "complete"
e, em caso positivo, chame uma função para disparar todos os manipuladores prontos.Os manipuladores registrados com docReady()
têm garantia de serem demitidos na ordem em que foram registrados.
Se você chamar docReady(fn)
depois que o documento já estiver pronto, a chamada de retorno será agendada para execução assim que o tópico de execução atual for concluído utilizando setTimeout(fn, 1)
. Isto permite que o código de chamada sempre assuma que eles são callbacks assíncronos que serão chamados mais tarde, mesmo que mais tarde seja assim que a thread atual do JS termine e ele preserve a ordem de chamada.
Seu método (colocar o roteiro antes da etiqueta de fechamento do corpo)
<script>
myFunction()
</script>
</body>
</html>
é uma maneira confiável de suportar antigos e novos navegadores.