jQuery document.createElement equivalente?

1251

Estou refatorando algum código JavaScript antigo e há muita manipulação de DOM acontecendo.

var d = document;
var odv = d.createElement("div");
odv.style.display = "none";
this.OuterDiv = odv;

var t = d.createElement("table");
t.cellSpacing = 0;
t.className = "text";
odv.appendChild(t);

Gostaria de saber se existe uma maneira melhor de fazer isso usando o jQuery. Eu tenho experimentado com:

var odv = $.create("div");
$.append(odv);
// And many more

Mas não tenho certeza se isso é melhor.

Rob Stevenson-Leggett
fonte
jsben.ch/#/ARUtz - uma referência para jQuery vs createElement
EscapeNetscape
Possível duplicata Criando um elemento div em jQuery
T.Todua
TypeError não capturado: $ .Create não é uma função
Tyguy7

Respostas:

1290

Aqui está o seu exemplo na linha "um".

this.$OuterDiv = $('<div></div>')
    .hide()
    .append($('<table></table>')
        .attr({ cellSpacing : 0 })
        .addClass("text")
    )
;

Atualização : pensei em atualizar este post, pois ele ainda recebe bastante tráfego. Nos comentários abaixo, há alguma discussão sobre $("<div>")vs $("<div></div>")vs $(document.createElement('div'))como uma maneira de criar novos elementos, e qual é "melhor".

Eu montei uma pequena referência e aqui estão aproximadamente os resultados de repetir as opções acima 100.000 vezes:

jQuery 1.4, 1.5, 1.6

               Chrome 11  Firefox 4   IE9
<div>            440ms      640ms    460ms
<div></div>      420ms      650ms    480ms
createElement    100ms      180ms    300ms

jQuery 1.3

                Chrome 11
<div>             770ms
<div></div>      3800ms
createElement     100ms

jQuery 1.2

                Chrome 11
<div>            3500ms
<div></div>      3500ms
createElement     100ms

Eu acho que não é uma grande surpresa, mas document.createElementé o método mais rápido. Obviamente, antes de começar a refatorar toda a sua base de código, lembre-se de que as diferenças de que estamos falando aqui (em todas as versões arcaicas do jQuery) equivalem a cerca de 3 milissegundos a cada mil elementos .


Atualização 2

Atualizado para o jQuery 1.7.2 e colocando o benchmark no JSBen.chqual provavelmente é um pouco mais científico do que meus benchmarks primitivos, além disso, ele pode ser disponibilizado agora!

http://jsben.ch/#/ARUtz

nickf
fonte
70
Você verá que document.createElement é muito mais rápido do que o jQuery converter sua string html em um elemento. (apenas no caso você tem um desejo de tornar as coisas mais eficiente)
Sugendran
25
Isso é verdade para jQuery <1.3. É velocidade equivalente agora, eu acredito.
22430 Rob Stevenson-Leggett
15
@ Kevin, isso é verdade, no entanto, faz com que o jQuery faça mais trabalho (ele executa um regex para adicionar a tag de fechamento), então eu prefiro o método acima. Além disso, ele diferencia seu código do $('div')qual é visualmente muito semelhante, mas funcionalmente separado.
nickf
14
Então, basicamente, uma combinação de @Sungendran e @nickf seria $(document.createElement('div'))e deveria ser a mais rápida?
Kolky
14
Eu acho que o caminho "correto" é $ ('<div />'), com IMO, tem ainda mais "significado", pois é bastante óbvio que você está criando um Nó. O ruim é que desta maneira quebra a sintaxe destacada em todos os editores = (
Erik Escobedo
139

O simples fornecimento do HTML dos elementos que você deseja adicionar a um construtor jQuery $()retornará um objeto jQuery do HTML recém-criado, adequado para ser anexado ao DOM usando o append()método jQuery .

Por exemplo:

var t = $("<table cellspacing='0' class='text'></table>");
$.append(t);

Você pode preencher essa tabela programaticamente, se desejar.

Isso permite que você especifique qualquer HTML arbitrário que desejar, incluindo nomes de classe ou outros atributos, que você pode achar mais conciso do que usar createElemente, em seguida, definir atributos como cellSpacinge classNamevia JS.

Adam Bellaire
fonte
7
Talvez isso tenha sido óbvio e indicado pelo seu exemplo, mas a criação de um elemento DOM do jQuery usando a sintaxe $ ("<html string>") não pode ser anexada ao DOM usando o método <element> .appendChild nativo ou similar. Você deve usar o método de adição de jQuery.
830 Adam
4
$(htmlStr)é implementado como document.createElement("div").innerHTML = htmlStr. Em outras palavras, ele chama o analisador HTML do navegador. O HTML malformado é diferente no IE em comparação com outros navegadores.
Matthew
2
O objeto @Adam jQuery tem a getfunção que retorna o elemento DOM nativo. (Eu sei que este tópico é antigo, mas eu o adiciono para referência. ;-)) #
Constantino Tsarouhas 17/05/2012
1
Se você está tendo problemas com a tentativa string HTML para analisá-lo com jQuery.parseHTML
fguillen
1
@ Adam Ou, se é mais fácil em seu fluxo de código / olhos, você pode fazer[dom element].appendChild($('<html>')[0]);
ACK_stoverflow
49

Eu estou fazendo assim:

$('<div/>',{
    text: 'Div text',
    class: 'className'
}).appendTo('#parentDiv');
kami
fonte
44

já que jQuery1.8usar $.parseHTML()para criar elementos é uma escolha melhor.

existem dois benefícios:

1.se você usar da maneira antiga, que pode ser algo como $(string), o jQuery examinará a string para garantir que você deseja selecionar uma tag html ou criar um novo elemento. Ao usar $.parseHTML(), você diz ao jQuery que deseja criar um novo elemento explicitamente, para que o desempenho possa ser um pouco melhor.

2.Muito mais importante é que você pode sofrer ataques entre sites ( mais informações ) se você usar o modo antigo. se você tiver algo como:

    var userInput = window.prompt("please enter selector");
    $(userInput).hide();

um bandido pode entrar <script src="xss-attach.js"></script>para provocar você. felizmente, $.parseHTML()evite esse embaraço para você:

var a = $('<div>')
// a is [<div>​</div>​]
var b = $.parseHTML('<div>')
// b is [<div>​</div>​]
$('<script src="xss-attach.js"></script>')
// jQuery returns [<script src=​"xss-attach.js">​</script>​]
$.parseHTML('<script src="xss-attach.js"></script>')
// jQuery returns []

No entanto, observe que aé um objeto jQuery enquanto bé um elemento html:

a.html('123')
// [<div>​123​</div>​]
b.html('123')
// TypeError: Object [object HTMLDivElement] has no method 'html'
$(b).html('123')
// [<div>​123​</div>​]
Brian
fonte
"Melhor escolha" para "criar [qualquer] elemento" pode ser forte. A resposta de @ siergiej faz um bom trabalho ao dizer que parseHTMLé bom para html proveniente de fontes externas, mas que " todo o impulso se foi depois de agrupar os resultados em um novo objeto jQuery ". Ou seja, se você deseja codificar a criação de um novo elemento html envolto em jQuery, o $("<div>stuff</div>")estilo ainda parece ganhar.
Ruffin
38

ATUALIZAR

Desde as versões mais recentes do jQuery, o método a seguir não atribui propriedades passadas no segundo objeto

Resposta anterior

Eu sinto que usar document.createElement('div')junto com jQueryé mais rápido:

$(document.createElement('div'), {
    text: 'Div text',
    'class': 'className'
}).appendTo('#parentDiv');
Om Shankar
fonte
29

Embora essa seja uma pergunta muito antiga, pensei que seria bom atualizá-la com informações recentes;

Desde o jQuery 1.8, existe uma função jQuery.parseHTML () que agora é a maneira preferida de criar elementos. Além disso, há alguns problemas na análise de HTML por $('(html code goes here)')exemplo, o site oficial do jQuery menciona o seguinte em uma de suas notas de versão :

Análise de HTML relaxada: Você pode novamente ter espaços à esquerda ou novas linhas antes das tags em $ (htmlString). Ainda recomendamos enfaticamente que você use $ .parseHTML () ao analisar o HTML obtido de fontes externas e poderá fazer novas alterações na análise de HTML no futuro.

Para se relacionar com a pergunta real, o exemplo fornecido pode ser traduzido para:

this.$OuterDiv = $($.parseHTML('<div></div>'))
    .hide()
    .append($($.parseHTML('<table></table>'))
        .attr({ cellSpacing : 0 })
        .addClass("text")
    )
;

que, infelizmente, é menos conveniente do que usar apenas $(), mas oferece mais controle; por exemplo, você pode optar por excluir as tags de script (isso deixará os scripts embutidos como se onclickfossem):

> $.parseHTML('<div onclick="a"></div><script></script>')
[<div onclick=​"a">​</div>​]

> $.parseHTML('<div onclick="a"></div><script></script>', document, true)
[<div onclick=​"a">​</div>​, <script>​</script>​]

Além disso, aqui está uma referência da resposta principal ajustada à nova realidade:

Link JSbin

jQuery 1.9.1

  $ .parseHTML: 88ms
  $ ($. parseHTML): 240ms
  <div> </div>: 138ms
  <div>: 143ms
  createElement: 64ms

Parece que parseHTMLestá muito mais perto do createElementque $(), mas todo o aumento se foi depois de agrupar os resultados em um novo objeto jQuery

siergiej
fonte
11
var mydiv = $('<div />') // also works
Shimon Doodkin
fonte
6
var div = $('<div/>');
div.append('Hello World!');

É a maneira mais curta / fácil de criar um elemento DIV no jQuery.

AcidicChip
fonte
5

Acabei de criar um pequeno plugin jQuery para isso: https://github.com/ern0/jquery.create

Segue sua sintaxe:

var myDiv = $.create("div");

O ID do nó DOM pode ser especificado como segundo parâmetro:

var secondItem = $.create("div","item2");

Isto é sério? Não. Mas essa sintaxe é melhor que $ ("<div> </div>") e é um valor muito bom para esse dinheiro.

Sou um novo usuário do jQuery, alternando do DOMAssistant, que possui uma função semelhante: http://www.domassistant.com/documentation/DOMAssistantContent-module.php

Meu plugin é mais simples, acho que attrs e o conteúdo é melhor adicionar por meio de métodos de encadeamento:

$("#container").append( $.create("div").addClass("box").html("Hello, world!") );

Além disso, é um bom exemplo para um simples plugin do jQuery (o 100º).

ern0
fonte
4

É tudo bem direto! Heres alguns exemplos rápidos ...


var $example = $( XMLDocRoot );

var $element = $( $example[0].createElement('tag') );
// Note the [0], which is the root

$element.attr({
id: '1',
hello: 'world'
});

var $example.find('parent > child').append( $element );
Randy
fonte
1

Como não foi mencionado nas respostas anteriores, estou adicionando um exemplo prático de como criar elementos com o jQuery mais recente, também com atributos adicionais como conteúdo, classe ou retorno de chamada onclick:

const mountpoint = 'https://jsonplaceholder.typicode.com/users'

const $button = $('button')
const $tbody = $('tbody')

const loadAndRender = () => {
  $.getJSON(mountpoint).then(data => {

    $.each(data, (index, { id, username, name, email }) => {
      let row = $('<tr>')
        .append($('<td>', { text: id }))
        .append($('<td>', {
          text: username,
          class: 'click-me',
          on: {
            click: _ => {
              console.log(name)
            }
          }
        }))
        .append($('<td>', { text: email }))

      $tbody.append(row)
    })

  })
}

$button.on('click', loadAndRender)
.click-me {
  background-color: lightgrey
}
<table style="width: 100%">
  <thead>
    <tr>
      <th>ID</th>
      <th>Username</th>
      <th>Email</th>
    </tr>
  </thead>
  <tbody>
  
  </tbody>
</table>

<button>Load and render</button>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

Vladislav Ladicky
fonte
-2

jQuery pronto para uso não tem o equivalente a um createElement. De fato, a maioria do trabalho do jQuery é feita internamente usando innerHTML em vez de pura manipulação de DOM. Como Adam mencionou acima, é assim que você pode obter resultados semelhantes.

Também existem plugins disponíveis que fazem uso do DOM sobre innerHTML, como appendDOM , DOMEC e FlyDOM , entre outros . Em termos de desempenho, o jquery nativo ainda é o de melhor desempenho (principalmente porque usa o innerHTML)

James Hughes
fonte
5
Você deve se atualizar. O jQuery não usa innerHtml, mas analisa a string HTML e constrói internamente uma árvore DOM usando document.createElement (). Este é o jQuery principal.
Vincent Robert