Qual é o equivalente não-jQuery de '$ (document) .ready ()'?

444

Qual é o equivalente não-jQuery $(document).ready()?

TIMEX
fonte
4
Se você deseja reproduzir o $(document).ready()evento do jQuery sem usar nenhuma biblioteca, veja isso: stackoverflow.com/questions/1795089/…
CMS
@OP: confira a página 89 de Técnicas Pro JavaScript para uma implementação de baunilha JavaScript $(document).ready()- books.google.com/… . Ele também usa a addEventabstração de ligação evento escrito por Dean Edwards, o código de que também está no livro :)
Russ Cam
2
possível duplicado de $ (documento). já equivalente sem jQuery
Qantas 94 Heavy

Respostas:

75

O bom $(document).ready()é que ele dispara antes window.onload. A função de carregamento aguarda até que tudo seja carregado, incluindo imagens e ativos externos. $(document).ready, no entanto, é acionado quando a árvore DOM está concluída e pode ser manipulada. Se você deseja obter o DOM pronto, sem o jQuery, verifique esta biblioteca. Alguém extraiu apenas a readyparte do jQuery. É agradável e pequeno e você pode achar útil:

já está no Google Code

Doug Neiner
fonte
4
Rede de códigos DomReady! via @CMS no github: github.com/cms/domready/network
Kzqai
44
Isso não responde à pergunta nem mostra nenhum código não-jQuery. Como conseguiu tantos votos positivos?
Daniel W.
3
@DanielW. Porque é simples e prático. A maioria de nós veio aqui procurando uma maneira de garantir que o DOM esteja pronto para ser usado pelo código javascript.
Abarazal
Sim, mas alguns de nós vieram aqui para uma resposta real.
Slbox
611

Isso funciona perfeitamente, da ECMA

document.addEventListener("DOMContentLoaded", function() {
  // code...
});

O window.onloadnão é igual ao JQuery $(document).readyporque $(document).readyaguarda apenas a árvore DOM enquanto window.onloadverifica todos os elementos, incluindo ativos e imagens externos.

EDITAR : Adicionado IE8 e equivalente mais antigo, graças à observação de Jan Derk . Você pode ler a fonte desse código no MDN neste link :

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "interactive") {
        // Initialize your application or run some code.
    }
}

Existem outras opções além de "interactive". Vejo o link MDN para detalhes.

sospedra
fonte
Concordando com Benjamin. Você não pode simplesmente usar o attachEvent. Por exemplo, no Chrome, você obtém: TypeError não capturado: document.attachEvent não é uma função. Use a resposta vinculada de Jan Derk.
Manuel Arwed Schmidt 15/02
9
E se o documento já estiver carregado quando esse script for chamado? Nada vai acontecer :(
oriadam
8
@Deerloper Não, apenas tentou fazê-lo no console Chrome - nada aconteceu: document.addEventListener("DOMContentLoaded",function(){console.log(123)})experimentá-lo agora
oriadam
2
Suporte do DOMContentLoaded nos navegadores: caniuse.com/domcontentloaded
Guillaume Husta
1
@elliottregan isso é verdade Eu removo o comentário para evitar poluir este tópico. Sugiro que todos façam o mesmo :) E deixe um comentário, se necessário, apontando o comentário, se necessário. Desde que é um extra porque vai além das questões OC
Sospedra
43

Uma coisinha que eu montei

domready.js

(function(exports, d) {
  function domReady(fn, context) {

    function onReady(event) {
      d.removeEventListener("DOMContentLoaded", onReady);
      fn.call(context || exports, event);
    }

    function onReadyIe(event) {
      if (d.readyState === "complete") {
        d.detachEvent("onreadystatechange", onReadyIe);
        fn.call(context || exports, event);
      }
    }

    d.addEventListener && d.addEventListener("DOMContentLoaded", onReady) ||
    d.attachEvent      && d.attachEvent("onreadystatechange", onReadyIe);
  }

  exports.domReady = domReady;
})(window, document);

Como usá-lo

<script src="domready.js"></script>
<script>
  domReady(function(event) {
    alert("dom is ready!");
  });
</script>

Você também pode alterar o contexto em que o retorno de chamada é executado passando um segundo argumento

function init(event) {
  alert("check the console");
  this.log(event);
}

domReady(init, console);
Obrigado
fonte
2
Obrigado. Eu gosto do fato de que é compatível com versões anteriores. Seguir em frente não significa apenas deixar pessoas menos afortunadas para trás. Não ser capaz de usar um navegador moderno (por qualquer motivo) é lamentável ...
CO
28

Agora que é 2018, aqui está um método rápido e simples.

Isso adicionará um ouvinte de evento, mas se ele já tiver sido acionado, verificaremos se o dom está em um estado pronto ou completo. Isso pode disparar antes ou depois do carregamento dos sub-recursos (imagens, folhas de estilo, molduras etc.).

function domReady(fn) {
  // If we're early to the party
  document.addEventListener("DOMContentLoaded", fn);
  // If late; I mean on time.
  if (document.readyState === "interactive" || document.readyState === "complete" ) {
    fn();
  }
}

domReady(() => console.log("DOM is ready, come and get it!"));

Leituras adicionais


Atualizar

Aqui estão alguns ajudantes rápidos de utilitários que usam o ES6 Import & Export que eu escrevi e que também incluem o TypeScript. Talvez eu possa criar uma biblioteca rápida que possa ser instalada em projetos como uma dependência.

Javascript

export const domReady = (callBack) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

TypeScript

export const domReady = (callBack: () => void) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack: () => void) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

Promessas

export const domReady = new Promise(resolve => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', resolve);
  }
  else {
    resolve();
  }
});

export const windowReady = new Promise(resolve => {
  if (document.readyState === 'complete') {
    resolve();
  }
  else {
    window.addEventListener('load', resolve);
  }
});
CTS_AE
fonte
16

De acordo com http://youmightnotneedjquery.com/#ready, um bom substituto que ainda funciona com o IE8 é

function ready(fn) {
  if (document.readyState != 'loading') {
    fn();
  } else if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', fn);
  } else {
    document.attachEvent('onreadystatechange', function() {
      if (document.readyState != 'loading')
        fn();
    });
  }
}

// test
window.ready(function() {
    alert('it works');
});

melhorias : Pessoalmente, eu também verificaria se o tipo de fné uma função. E como sugeriu a @elliottregan, remova o ouvinte do evento após o uso.

O motivo pelo qual respondi tarde a essa pergunta é porque estava procurando por essa resposta, mas não a encontrei aqui. E acho que essa é a melhor solução.

Thomas online
fonte
1
Sim, esta é a melhor resposta na minha opinião. Fácil de ler e executa o código mesmo se o DOM já estiver carregado. A única coisa que gostaria de adicionar é remover o eventlistener após o evento ser disparado.
Elliottregan 24/04/19
14

Existe uma substituição baseada em padrões, DOMContentLoaded , suportada por mais de 90% dos navegadores, mas não o IE8 (portanto, abaixo do código usado pelo JQuery para suporte ao navegador) :

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work
});

A função nativa do jQuery é muito mais complicada do que apenas window.onload, como mostrado abaixo.

function bindReady(){
    if ( readyBound ) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", function(){
            document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
            jQuery.ready();
        }, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent("onreadystatechange", function(){
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", arguments.callee );
                jQuery.ready();
            }
        });

        // If IE and not an iframe
        // continually check to see if the document is ready
        if ( document.documentElement.doScroll && window == window.top ) (function(){
            if ( jQuery.isReady ) return;

            try {
                // If IE is used, use the trick by Diego Perini
                // http://javascript.nwbox.com/IEContentLoaded/
                document.documentElement.doScroll("left");
            } catch( error ) {
                setTimeout( arguments.callee, 0 );
                return;
            }

            // and execute any waiting functions
            jQuery.ready();
        })();
    }

    // A fallback to window.onload, that will always work
    jQuery.event.add( window, "load", jQuery.ready );
}
Zigri2612
fonte
1
O novo jQuery descartou o suporte para navegadores mais antigos e agora eles só usam DOMContentLoadede loadeventos addEventListener, e primeiro o acionamento remove os dois ouvintes, para que não sejam acionados duas vezes.
jcubic
8

Em simples baunilha JavaScript, sem bibliotecas? É um erro. $é simplesmente um identificador e é indefinido, a menos que você o defina.

O jQuery define $como seu próprio "objeto tudo" (também conhecido como jQuerypara que você possa usá-lo sem entrar em conflito com outras bibliotecas). Se você não estiver usando o jQuery (ou alguma outra biblioteca que o defina), $não será definido.

Ou você está perguntando qual é o equivalente em JavaScript simples? Nesse caso, você provavelmente deseja window.onload, o que não é exatamente equivalente, mas é a maneira mais rápida e fácil de se aproximar do mesmo efeito no JavaScript vanilla.

Brian Campbell
fonte
39
Para os muitos que rejeitam essa resposta (e as outras abaixo): quando essa pergunta foi feita, ela dizia simplesmente: "O que é $ (document) .ready () em javascript? Não em jquery. O que é?" Parecia que ele estava perguntando o que isso significava em simples baunilha JavaScript sem o jQuery carregado. Na minha resposta, tentei responder a essa pergunta, bem como fornecer a resposta mais fácil e fácil para JavaScript simples, sem jQuery ou outras bibliotecas, caso fosse o que ele quis dizer. Observe que todo o contexto extra foi adicionado por outras pessoas, adivinhando o que a pergunta estava perguntando, não o pôster original.
Brian Campbell
5

A maneira mais fácil nos navegadores recentes seria usar o GlobalEventHandlers apropriado , onDOMContentLoaded , onload , onloadeddata (...)

onDOMContentLoaded = (function(){ console.log("DOM ready!") })()

onload = (function(){ console.log("Page fully loaded!") })()

onloadeddata = (function(){ console.log("Data loaded!") })()

O evento DOMContentLoaded é acionado quando o documento HTML inicial tiver sido completamente carregado e analisado, sem aguardar folhas de estilo, imagens e sub-quadros para concluir o carregamento. Um carregamento de evento muito diferente deve ser usado apenas para detectar uma página totalmente carregada. É um erro incrivelmente popular usar o load em que DOMContentLoaded seria muito mais apropriado, portanto, tenha cuidado.

https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

A função usada é um IIFE, muito útil neste caso, pois se aciona quando pronto:

https://en.wikipedia.org/wiki/Immedately-invoked_function_expression

É obviamente mais apropriado colocá-lo no final de qualquer script.

No ES6, também podemos escrevê-lo como uma função de seta:

onload = (() => { console.log("ES6 page fully loaded!") })()

O melhor é usar os elementos DOM, podemos esperar que qualquer variável esteja pronta, que aciona um IIFE com flecha.

O comportamento será o mesmo, mas com menos impacto na memória.

footer = (() => { console.log("Footer loaded!") })()
<div id="footer">

Em muitos casos, o objeto de documento também é acionado quando pronto , pelo menos no meu navegador. A sintaxe é muito boa, mas precisa de mais testes sobre compatibilidade.

document=(()=>{    /*Ready*/   })()
NVRM
fonte
Um IIFE poderia disparar antes que o DOM terminasse de carregar elementos depois dele?
CTS_AE
Claro, é apenas uma função, uma função anônima, em um fechamento.
NVRM
0

O corpo onLoad também pode ser uma alternativa:

<html>
<head><title>Body onLoad Exmaple</title>

<script type="text/javascript">
    function window_onload() {
        //do something
    }
</script>

</head>
<body onLoad="window_onload()">

</body>
</html>
joan16v
fonte