Qual é a maneira mais eficiente de criar elementos HTML usando jQuery?

425

Recentemente, venho fazendo muitos pop-ups de janela modal e o que não, para o qual usei o jQuery. O método que eu usei para criar os novos elementos na página tem sido esmagadoramente ao longo das linhas de:

$("<div></div>");

No entanto, estou sentindo que esse não é o melhor ou o método mais eficiente de fazer isso. Qual é a melhor maneira de criar elementos no jQuery a partir de uma perspectiva de desempenho?

Esta resposta tem os parâmetros de referência para as sugestões abaixo.

Darko Z
fonte
1
Experimente remover estilos também e veja se isso acelera as coisas. Acho que as aplicações e atualizações de CSS atrasam mais as coisas em páginas grandes para mim.
CVertex
3
Cuidado com a otimização prematura - se você não estiver fazendo isso para centenas de elementos DOM de cada vez, ou usando navegadores MUITO antigos, provavelmente não notará nenhuma diferença no desempenho do navegador.
Blazemonger 31/07/12
1
@Blazemonger Não era tanto que eu precisava de um método mais eficiente de criar elementos DOM, mas a situação em que eu estava me fez refletir sobre quais são as alternativas e quão eficientes elas podem ser.
precisa
2
O jQuery é uma biblioteca - você quase sempre incorre em custos indiretos de desempenho por esse motivo: é como conversar com alguém através de um intérprete. A menos que você queira usar JavaScript bruto, aproveite a rapidez com que é gravado $ ('<div>') e aceite o impacto no desempenho.
precisa saber é o seguinte
1
jsben.ch/#/bgvCV <= esta referência deve responder à sua pergunta
EscapeNetscape 7/16

Respostas:

307

Eu uso $(document.createElement('div')); Benchmarking mostra que esta técnica é a mais rápida. Especulo que isso ocorre porque o jQuery não precisa identificá-lo como um elemento e criar o próprio elemento.

Você realmente deve executar benchmarks com diferentes mecanismos Javascript e pesar seu público com os resultados. Tome uma decisão a partir daí.

strager
fonte
16
jQuery "anexa" ao DOM? Onde? Isso não faz muito sentido para mim - para onde iria a div?
Strager
28
uma div criada no jquery deve ser adicionada como no javascript. $ ('<div>') por si só não é anexado ao DOM até você anexá-lo a alguma coisa.
Owen
6
@ David - obviamente, você está certo. Observarei que adicionei o comentário há cerca de 2 anos, exatamente quando eu estava começando a aprender jQuery. Você precisaria fazer um appendTo... Como os comentários estavam obviamente errados, eu os removi.
precisa saber é o seguinte
16
A referência de benchmarking é ótima, mas isso também está testando a criação de dezenas de milhares de elementos. Quando você NUNCA estará lidando com tantos elementos em uma situação típica? As chances são de que você tenha coisas maiores com que se preocupar do que como criar um elemento. document.createElement "Ran 39.682 vezes em 0,097 segundos", enquanto $ ('<div>') "Ran 12,642 em 0,068 segundos." Eu diria que se algo pode correr milhares de vezes em menos de um segundo, você está seguro.
precisa saber é o seguinte
20
Além disso, usando $ (document.createElement ('div')); Eu diria que é menos eficiente, porque leva mais tempo para escrever para a quantidade substancialmente pequena de benefícios que você obterá no navegador se estiver criando apenas um elemento por vez aqui e ali. Tecnicamente, o jQuery em si é menos eficiente como uma biblioteca devido aos custos de pesquisa e às despesas gerais incorridas ao usá-lo. Se alguém quer economizar milésimos de segundo precioso usando document.createElement em vez de $ ('<div>'), não deve usar jQuery:] porque $ ('<div>') é um dos motivos pelos quais você o usa!
Danny Bullis
163

pessoalmente, eu sugeriria (para facilitar a leitura):

$('<div>');

alguns números das sugestões até agora (safari 3.2.1 / mac os x):

var it = 50000;

var start = new Date().getTime();
for (i = 0; i < it; ++i)  {
  // test creation of an element 
  // see below statements
}
var end = new Date().getTime();
alert( end - start );                

var e = $( document.createElement('div') );  // ~300ms
var e = $('<div>');                          // ~3100ms
var e = $('<div></div>');                    // ~3200ms
var e = $('<div/>');                         // ~3500ms              
Owen
fonte
15
Nos documentos do jquery: 'Ao criar elementos únicos, use a tag de fechamento ou o formato XHTML. Por exemplo, para criar uma extensão, use $ ("<span />") ou $ ("<span> </span>") em vez de sem a barra / tag de fechamento. '
Tvanfosson
6
@ Owen, esse comportamento é um bug, não um recurso. Lixo para dentro, lixo para fora - acontece que o lixo que você recebe é aceitável. Não confie nele entre as versões do jQuery, a menos que a especificação da função seja alterada.
Strager
2
Como esperado, ver números semelhantes no Mac OS X Chrome (100ms para createElement () vs. 500ms de análise de texto) e no Mac OS X Firefox (350ms vs. 1000ms). Obrigado por escrever o loop de teste.
Annika Backstrom
3
@tvanfosson Aparentemente, isso mudou nos documentos atuais: "Quando o parâmetro possui uma única tag (com tag de fechamento opcional ou fechamento rápido) - $ (" <img /> ") ou $ (" <img> " ), $ ("<a> </a>") ou $ ("<a>") - jQuery cria o elemento usando a função nativa JavaScript createElement (). "
Metatron
3
@MarcStober Sem ofensas. Ainda está aqui: http://api.jquery.com/jQuery/#jQuery2 . Os documentos mencionam tag de fechamento opcional ou fechamento rápido
metatron 23/02
155

Questão:

Qual é a maneira mais eficiente de criar elementos HTML usando jQuery?

Responda:

Como é sobre jQueryisso, acho melhor usar essa abordagem (limpa) (você está usando)

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'text':'Text Only',
}).on('click', function(){
    alert(this.id); // myDiv
}).appendTo('body');

DEMO.

Dessa forma, você pode até usar manipuladores de eventos para o elemento específico, como

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'style':'cursor:pointer;font-weight:bold;',
    'html':'<span>For HTML</span>',
    'click':function(){ alert(this.id) },
    'mouseenter':function(){ $(this).css('color', 'red'); },
    'mouseleave':function(){ $(this).css('color', 'black'); }
}).appendTo('body');

DEMO.

Mas quando você lida com muitos elementos dinâmicos, evite adicionar eventos handlersem um elemento específico. Em vez disso, use um manipulador de eventos delegados, como

$(document).on('click', '.myClass', function(){
    alert(this.innerHTML);
});

var i=1;
for(;i<=200;i++){
    $('<div/>', {
        'class':'myClass',
        'html':'<span>Element'+i+'</span>'
    }).appendTo('body');
}

DEMO.

Portanto, se você criar e anexar centenas de elementos com a mesma classe, ou seja, ( myClass), menos memória será consumida para manipulação de eventos, porque apenas um manipulador estará lá para fazer o trabalho para todos os elementos inseridos dinamicamente.

Atualização: Como podemos usar a seguinte abordagem para criar um elemento dinâmico

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    'size': '30'
}).appendTo("body");

Mas o sizeatributo não pode ser configurado usando essa abordagem usando jQuery-1.8.0ou mais tarde e aqui está um relatório de bug antigo , veja este exemplo usando o jQuery-1.7.2que mostra que o sizeatributo está configurado para 30usar o exemplo acima, mas usando a mesma abordagem que não podemos definir o sizeatributo usando jQuery-1.8.3, aqui é um violino que não funciona . Então, para definir o sizeatributo, podemos usar a seguinte abordagem

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    attr: { size: "30" }
}).appendTo("body");

Ou este

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    prop: { size: "30" }
}).appendTo("body");

Podemos passar attr/propcomo um objeto filho, mas ele funciona em jQuery-1.8.0 and laterversões, verifique este exemplo, mas não funcionará emjQuery-1.7.2 or earlier (não testado em todas as versões anteriores).

BTW, retirado do jQueryrelatório de erro

Existem várias soluções. O primeiro é não usá-lo, pois não economiza espaço e isso melhora a clareza do código:

Eles recomendaram o uso da seguinte abordagem ( funciona também nas anteriores , testadas em 1.6.4)

$('<input/>')
.attr( { type:'text', size:50, autofocus:1 } )
.val("Some text").appendTo("body");

Portanto, é melhor usar essa abordagem, IMO. Esta atualização é feita depois que eu li / encontrei esta resposta e, nesta resposta, mostra que se você usar em 'Size'(capital S)vez de 'size', simplesmente funcionará bem , mesmo emversion-2.0.2

$('<input>', {
    'type' : 'text',
    'Size' : '50', // size won't work
    'autofocus' : 'true'
}).appendTo('body');

Leia também sobre prop , porque há uma diferença, Attributes vs. Propertiesvaria de acordo com as versões.

The Alpha
fonte
Que tipo de sintaxe é esse $ ('<div />', {.........}), procurei e encontrei alguns similares usando $ ('<div>) .attr ( {......})?
Rafael Ruiz Tabares
@RafaelRuizTabares, $('<div>', {...})você está passando um objeto que contém todos os atributos e $('<div>').attr({...})está criando um elemento sem nenhum atributo, mas configurando os atributos usando o attr()método posteriormente.
The Alpha
@TheAlpha, onde posso encontrar informações sobre o que posso escrever em {}? Porque vejo que são atributos e eventos, mas para <div> você também usa html. Obrigado!
Rafael Ruiz Tabares
Pesquisar jQuery.comweb site poderia ser votos @RafaelRuizTabares, ou google it :-)
A Alpha
2
Esta é de longe a maneira mais limpa e legível! Provavelmente não é o caminho mais rápido, mas certamente menos propenso a erros na adição de strings. Obrigado @TheAlpha
Ares
37

Na verdade, se você estiver fazendo $('<div>'), o jQuery também usará document.createElement().

(Basta dar uma olhada na linha 117 ).

Há alguma sobrecarga de chamada de função, mas, a menos que o desempenho seja crítico (você está criando centenas [milhares] de elementos), não há muitas razões para voltar ao DOM simples .

Apenas a criação de elementos para uma nova página da web provavelmente é o caso em que é melhor se atentar à maneira do jQuery de fazer as coisas.

Edwin
fonte
20

Se você tiver muito conteúdo HTML (mais do que apenas uma única div), considere criar o HTML na página em um contêiner oculto, atualizá-lo e torná-lo visível quando necessário. Dessa forma, grande parte da sua marcação pode ser pré-analisada pelo navegador e evitar o atolamento do JavaScript quando chamada. Espero que isto ajude!

Collin Allen
fonte
Obrigado pelo conselho. Eu já usei essa abordagem antes, no entanto, neste caso específico, quero especificamente saber sobre a criação de elementos.
Darko Z
20

Esta não é a resposta correta para a pergunta, mas ainda gostaria de compartilhar isso ...

Usar apenas document.createElement('div')e pular o JQuery melhorará muito o desempenho quando você desejar criar muitos elementos rapidamente e anexar ao DOM.

Irshad
fonte
16

Acho que você está usando o melhor método, embora possa otimizá-lo para:

 $("<div/>");
tvanfosson
fonte
11

Você não precisa de desempenho bruto de uma operação que será executada com pouca frequência do ponto de vista da CPU.

yfeldblum
fonte
Depende da frequência com que você está fazendo isso.
Ricos Bradshaw
8
O OP está criando um pop-up modal . Esta operação não é repetida milhares de vezes por segundo. Em vez disso, é repetido talvez uma vez a cada poucos segundos, no máximo. Usar o jQuery(html :: String)método está perfeitamente bem. A menos que a situação seja extremamente incomum, é improvável que se obtenha melhor desempenho percebido . Gaste energia de otimização nos casos que poderiam usá-lo. Além disso, o jQuery é otimizado para velocidade de várias maneiras. Faça coisas sãs com isso e confie, mas verifique se é rápido.
Yfeldblum
9

Você precisará entender que a importância do desempenho da criação de elementos é irrelevante no contexto do uso do jQuery.

Lembre-se de que não existe um propósito real de criar um elemento, a menos que você realmente o utilize.

Você pode ficar tentado a testar o desempenho com algo como $(document.createElement('div'))vs. $('<div>')e obter grandes ganhos de desempenho usando$(document.createElement('div')) mas esse é apenas um elemento que ainda não está no DOM.

No entanto, no final do dia, você desejará usar o elemento de qualquer maneira, para que o teste real inclua f.ex. .appendTo ();

Vamos ver, se você testar o seguinte um contra o outro:

var e = $(document.createElement('div')).appendTo('#target');
var e = $('<div>').appendTo('#target');
var e = $('<div></div>').appendTo('#target');
var e = $('<div/>').appendTo('#target');

Você notará que os resultados variam. Às vezes, uma maneira tem melhor desempenho que a outra. E isso ocorre apenas porque a quantidade de tarefas em segundo plano no seu computador muda com o tempo.

Teste-se aqui

Portanto, no final do dia, você deseja escolher a maneira menor e mais legível de criar um elemento. Dessa forma, pelo menos, seus arquivos de script serão os menores possíveis. Provavelmente, um fator mais significativo no ponto de desempenho do que a maneira de criar um elemento antes de usá-lo no DOM.

Jani Hyytiäinen
fonte
Eu sei que isso é velho, mas não há nenhuma necessidade de jQuery no primeiro exemplo:document.getElementById('target).appendChild(document.createElement('div'));
hisdrewness
7

Um ponto é que pode ser mais fácil fazer:

$("<div class=foo id=bar style='color:white;bgcolor:blue;font-size:12pt'></div>")

Depois, faça tudo isso com chamadas jquery.

Tobiah
fonte
3

Estou usando o jquery.min v2.0.3. É melhor para mim usar o seguinte:

var select = jQuery("#selecter");
jQuery("`<option/>`",{value: someValue, text: someText}).appendTo(select);

como segue:

var select = jQuery("#selecter");
jQuery(document.createElement('option')).prop({value: someValue, text: someText}).appendTo(select);

O tempo de processamento do primeiro código é muito menor que o segundo código.

Marcel GJS
fonte