Plug-in domReady necessário vs Jquery $ (document) .ready ()?

100

Estou usando RequireJS e preciso inicializar algo pronto para o DOM. Agora, RequireJS fornece o domReadyplugin , mas já temos o jQuery $(document).ready(), que está disponível para mim desde que solicitei o jQuery.

Portanto, tenho duas opções:

  1. Use o domReadyplugin:

    require(['domReady'], function (domReady) {
        domReady(function () {
            // Do my stuff here...
        });
    });
    
  2. Use $(document).ready():

    $(document).ready(function() {
        // Do my stuff here...
    });
    

Qual devo escolher e por quê?

Ambas as opções parecem funcionar conforme o esperado. Não estou confiante no do jQuery porque o RequireJS está fazendo sua mágica; isto é, como o RequireJS adicionará scripts dinamicamente, estou preocupado que o DOM pronto possa ocorrer antes que todos os scripts solicitados dinamicamente sejam carregados. Considerando que, RequireJS irá adicionar uma carga em JS adicional apenas para domReadyquando eu já tiver o jQuery necessário.

Questões

  • Por que o RequireJS fornece um domReadyplugin quando podemos ter o jQuery $(document).ready();? Não vejo nenhuma vantagem em incluir outra dependência.
  • Se for apenas para suprir uma necessidade, por que não fornecer um para AJAX para vários navegadores?

Até onde eu sei, um módulo que requer domReadynão será obtido ou executado depois que o documento estiver pronto, e você também poderia fazer o mesmo requerendo o jQuery:

require(['jQuery'], function ($) {
    $(document).ready(function () {
        // Do my stuff here...
    });
});

Para ser mais claro na minha pergunta: qual é a diferença entre exigir domReadyou jQuery?

Yugal Jindle
fonte
4
I am not confident in jquery's dom readyquero marcá-lo como ofensivo:p
Dakait
3
O dom ready do jQuery é perfeitamente confiável, mesmo no IE. Milhões de pessoas usam todos os dias sem saber ;-)
John Dvorak
1
Você controla para onde suas scripttags vão ou está escrevendo uma biblioteca / plug-in que outras pessoas usarão (e, portanto, elas estão no controle da localização das scripttags na marcação)?
TJ Crowder
3
Oh Deus .. leia com o contexto completo. I am not confident in jquery's dom ready because requirejs is doing its magic.Desde então, require está encapsulando jquery em um escopo local limitado. Esse não é o ponto. (no que diz respeito à questão).
Yugal Jindle
1
Obrigado, @TJCrowder pela edição.
Yugal Jindle

Respostas:

91

Parece que todos os pontos-chave já foram atingidos, mas alguns detalhes passaram despercebidos. Principalmente:

domReady

É um plugin e um módulo. Se você incluí-lo na matriz de requisitos com um acompanhamento, !seu módulo não será executado até que seja "seguro" para interagir com o DOM:

define(['domReady!'], function () {
    console.info('The DOM is ready before I happen');
});

Observe que o carregamento e a execução são diferentes; você deseja que todos os seus arquivos sejam carregados o mais rápido possível, é a execução do conteúdo que é sensível ao tempo.

Se você omitir o !, então é apenas um módulo normal que passa a ser uma função, que pode receber um retorno de chamada que não será executado antes que o DOM seja seguro para interagir com:

define(['domReady'], function (domReady) {
    domReady(function () {
        console.info('The DOM is ready before I happen');
    });
    console.info('The DOM might not be ready before I happen');        
});

Vantagem ao usar domReady como plugin

O código que depende de um módulo do qual, por sua vez, depende domReady!tem uma vantagem muito significativa: não precisa esperar que o DOM esteja pronto!

Digamos que temos um bloco de código, A, que depende de um módulo, B, do qual depende domReady!. Módulo B não terminará de carregar antes que o DOM esteja pronto. Por sua vez, A não funcionará antes de B ser carregado.

Se você fosse usar domReadycomo um módulo regular em B, também seria necessário que A dependesse domReady, bem como envolver seu código dentro de uma domReady()chamada de função.

Além disso, isso significa que domReady!desfruta da mesma vantagem sobre $(document).ready().

Re as diferenças entre domReady e $ (document) .ready ()

Ambos detectam se / quando o DOM está pronto essencialmente da mesma maneira.

Com medo de o jQuery disparar na hora errada

jQuery irá disparar qualquer retorno de chamada pronto, mesmo se o DOM carregar antes do jQuery (seu código não deve se importar com o que acontece primeiro).

fncomp
fonte
1
Linda, era isso que eu procurava. Razoável, bem suportado.
Yugal Jindle
Que bom que pude ajudar :-)
fncomp
@YugalJindle Falta algo para a recompensa? :)
fncomp
Eu estava apenas testando o que você escreveu - aqui está!
Yugal Jindle
Olhando para o código do plugin domReady ( github.com/requirejs/domReady/blob/master/domReady.js ), não vejo nenhuma razão para você precisar carregá-lo como 'domReady!' em vez de 'domReady' - você poderia me indicar o trecho de código que causa essa mudança de comportamento?
Jez
20

Uma tentativa de responder à sua pergunta principal:

Por que requirejsfornece um domReadyplugin quando podemos ter o jquery $(document).ready();?

Eles fazem duas coisas diferentes, na verdade. A domReadydependência de RequireJS significa que este módulo requer que o DOM seja completamente carregado antes de poder ser executado (e pode, portanto, ser encontrado em qualquer número de módulos em seu aplicativo, se você desejar), enquanto, em $(document).ready()vez disso, dispara suas funções de retorno de chamada quando o DOM é carregamento completo.

A diferença pode parecer sutil, mas pense no seguinte: eu tenho um módulo que precisa ser acoplado ao DOM de alguma forma, então posso depender dele domReadye acoplá-lo no momento da definição do módulo ou colocar um $(document).ready()no final dele com um retorno de chamada para uma função init para o módulo. Eu diria que a primeira abordagem é mais limpa.

Enquanto isso, se eu tiver um evento que precisa acontecer assim que o DOM estiver pronto, o $(document).ready()evento seria o ponto de partida, já que isso não depende em particular do RequireJS estar carregando módulos, desde que as dependências do código que você está chamando de são atendidos.

Também vale a pena considerar que você não usa necessariamente RequireJS com jQuery. Qualquer módulo de biblioteca que precise de acesso DOM (mas não dependa do jQuery) ainda seria útil usando domReady.

Gert Sønderby
fonte
domReadynão é uma dependência para requirejs. Seria uma dependência para o código se você estiver usando domReadypara o evento DocumentReady. Além disso, você parece estar confuso.
Yugal Jindle
1
Ótima resposta e uma dica importante para as sutilezas que muitos desenvolvedores muitas vezes não percebem (incluindo eu ;-)).
Golo Roden
1
Yugal, eu estava me referindo domReadycomo uma dependência, porque é assim que é usado. Não como uma dependência do RequireJS, mas do módulo onde é usado. Talvez eu deva deixar isso mais claro no meu texto, você tem sugestões de como?
Gert Sønderby
Por favor, veja o Update2 na questão. Pode ser que não estejamos na mesma página.
Yugal Jindle
Yugal, e se você usar MooTools? Qooxdoo? Qualquer coisa que não seja jQuery? RequireJS não é casado com jQuery, embora eles trabalhem muito bem juntos.
Gert Sønderby
6

Respondendo às suas balas em ordem de aparecimento:

  • Ambos realizam a mesma coisa
  • Se você tiver reservas sobre jquery por qualquer motivo, use domReady
  • Correto, então apenas use jQuery
  • Porque nem todo mundo usa jQuery
  • Eu concordo, basta usar jQuery
  • Plugins por definição 'alimentam uma necessidade'.
  • Cross Browser ajax não é uma coisa. Domínio cruzado? Provavelmente existe e, se não houver, não há necessidade de se alimentar.
  • , -, -, - Está bem

Quando se trata disso, você está pensando demais nisso. É um mecanismo para executar javascript em domReady. Se você não tivesse o jQuery, eu recomendaria o plugin domReady. Como você tem o jQuery, não carregue mais scripts para fazer algo que já está disponível.

Atualização de clareza

O plugin domReady coleta funções para chamar quando o documento está 'pronto'. Se já estiver carregado, eles serão executados imediatamente.

JQuery coleta funções e vincula um objeto adiado ao dom que está 'pronto'. Quando o dom estiver pronto, o objeto diferido será resolvido e as funções serão acionadas. Se o dom já estiver 'pronto', o adiado já estará resolvido e a função será executada imediatamente.

Isso significa que efetivamente eles fazem exatamente a mesma coisa.

Awbergs
fonte
0

Depois de alguns experimentos com requirejs com vários módulos, sugiro usar domReady .

Percebi que a função associada a $ (document) .ready (...) não é chamada quando vários módulos são carregados por requirejs. Suspeito que o dom está se preparando antes que todo o código requirejs seja executado e o manipulador de retorno de chamada pronto do jquery seja chamado antes de ser vinculado à função definida pelo usuário, ou seja, dentro do código do módulo principal.

require(['jquery',
    'underscore',
    'text!some_template.html',
    './my_module_1',
    './my_module_2',
    'domReady',
    'other_dependency_1',
    'other_dependency_2'
    ], function($, _, someTemplate, myModule1, myModule2, domReady) {

    $(document).ready(function() {
        console.info('This might never be executed.'); 
        console.info('Dom might get ready before requirejs would load modules.');
    });

    domReady(function () {
        console.info('This runs when the dom gets ready and modules are loaded.');
    });
});
Marcin Nowakowski
fonte
1
Duvido que, se você tiver todos os módulos em sua lista de dependências, todos serão buscados e colocados na memória. postar que jquery coleta instâncias dom.ready antes da execução.
Yugal Jindle
Se o DOM já estiver pronto, o retorno de chamada para $(document).readyserá executado imediatamente.
Danyal Aytekin
-1

Descobri que faço isso como parte da entrada principal para que todo o meu javascript tenha a garantia de que o DOM está pronto e o jquery é carregado. Não tenho certeza se isso é bom, então qualquer feedback, mas aqui está meu main.js:

require(['domReady!'], function(domReady){
    console.log('dom is ready');
    require(['jquery', 'bootstrap'], function(){
        console.log('jquery loaded');
        require(['app'], function(app){
            console.log('app loaded');
        });
    });
});
Bil Simser
fonte