Inserindo elementos HTML com JavaScript

105

Em vez de pesquisar tediosamente soluções alternativas para cada tipo de atributo e evento ao usar a seguinte sintaxe:

elem = document.createElement("div");
elem.id = 'myID';
elem.innerHTML = ' my Text '
document.body.insertBefore(elem,document.body.childNodes[0]);

Existe uma maneira de simplesmente declarar todo o elemento HTML como uma string? gostar:

elem = document.createElement("<div id='myID'> my Text </div>");
document.body.insertBefore(elem,document.body.childNodes[0]);
O Flash
fonte

Respostas:

124

Em vez de mexer com innerHTMLele diretamente , pode ser melhor criar um fragmento e inserir:

function create(htmlStr) {
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}

var fragment = create('<div>Hello!</div><p>...</p>');
// You can use native DOM methods to insert the fragment:
document.body.insertBefore(fragment, document.body.childNodes[0]);

Benefícios:

  1. Você pode usar métodos DOM nativos para inserção, como insertBefore, appendChild etc.
  2. Você tem acesso aos nós DOM reais antes de eles serem inseridos; você pode acessar o objeto childNodes do fragmento.
  3. Usar fragmentos de documentos é muito rápido; mais rápido do que criar elementos fora do DOM e em certas situações mais rápido do que innerHTML.

Embora innerHTMLseja usado dentro da função, tudo está acontecendo fora do DOM, então é muito mais rápido do que você pensa ...

James
fonte
3
Aposto que este createDocumentFragment () não seria tão bom quanto o innerHTML "legado".
TheFlash
2
Este método funciona em todos os navegadores modernos. Para o IE 5.5 e anteriores, você pode executar uma verificação como :: if (document.createDocumentFragment) {create ('...'); } else {/ * Use innerHTML talvez * /}
James
32
crescentfresh, ajudo no SO porque gosto de ajudar as pessoas; Lamento se uma solução não é 100% operável em todas as situações. Se você está tão preocupado, por que não oferece sua própria solução em vez de ser desnecessariamente crítico com as respostas já oferecidas? Com qualquer abstração, sempre haverá casos extremos! Este é um ambiente de aprendizagem - não estamos aqui para dar às pessoas uma solução em um prato - estamos aqui para ajudar uns aos outros a se tornarem melhores no que fazemos! E desculpe, mas onde alguém mencionou "AJAX"?
James
1
Justo. Me desculpe. Eu simplesmente sinto que há tantas abstrações aqui com nenhuma advertência mencionada.
Crescent Fresh
1
isso é muito mais complexo do que precisa ser - a resposta de sime vidas é muito melhor
JonnyRaa
83

Você quer isso

document.body.insertAdjacentHTML( 'afterbegin', '<div id="myID">...</div>' );
Šime Vidas
fonte
13
não sei por que essa não é a resposta aceita. Isso é muito mais simples e mais obviamente correto
JonnyRaa
@JonnyLeeds isso não parece funcionar no bodyelemento, mas funciona bem em qualquer outro elemento.
Phill
1
@Phill Claro que funciona <body>. Na verdade, executá-lo <body>é meu método padrão de injetar coisas como folhas de estilo em páginas da web por meio do console. Que problema você está tendo?
Šime Vidas
@ ŠimeVidas provavelmente porque o elemento body não foi definido em tempo de execução ... eu parei sua linha com window.onload = function () {...} para evitar esse problema
GDY
@Grandy Phill escreveu que funciona em outros elementos. Se <body>fossem indefinidos, todos os outros elementos também seriam, então esse provavelmente não é o problema de Phill.
Šime Vidas
32

Dê uma olhada em insertAdjacentHTML

var element = document.getElementById("one");
var newElement = '<div id="two">two</div>'
element.insertAdjacentHTML( 'afterend', newElement )
// new DOM structure: <div id="one">one</div><div id="two">two</div>

position é a posição relativa ao elemento que você está inserindo adjacente a:

'beforebegin' Antes do próprio elemento

'afterbegin' Apenas dentro do elemento, antes de seu primeiro filho

'beforeend' Apenas dentro do elemento, após seu último filho

'afterend' Após o próprio elemento

svnm
fonte
17

No JavaScript antigo, você poderia fazer isso:

document.body.innerHTML = '<p id="foo">Some HTML</p>' + document.body.innerHTML;

Em resposta ao seu comentário:

[...] eu estava interessado em declarar a origem dos atributos e eventos de um novo elemento, não a origem innerHTMLde um elemento.

Você precisa injetar o novo HTML no DOM; é por isso que innerHTMLé usado no exemplo do JavaScript da velha escola. O innerHTMLdo BODYelemento é adicionado ao novo HTML. Não estamos realmente mexendo no HTML existente dentro do BODY.

Vou reescrever o exemplo mencionado acima para esclarecer isso:

var newElement = '<p id="foo">This is some dynamically added HTML. Yay!</p>';
var bodyElement = document.body;
bodyElement.innerHTML = newElement + bodyElement.innerHTML;
// note that += cannot be used here; this would result in 'NaN'

Usar uma estrutura JavaScript tornaria este código muito menos prolixo e melhoraria a legibilidade. Por exemplo, jQuery permite que você faça o seguinte:

$('body').prepend('<p id="foo">Some HTML</p>');
Mathias Bynens
fonte
Muito bom. Mas eu estava interessado em declarar a origem dos atributos e eventos de um novo elemento, não o innerHTML de um elemento.
TheFlash
1
document.getElementsByTagName('body')[0]pode de fato ser substituído por document.body, bom argumento. No entanto, se desejar preceder ou acrescentar o novo HTML a outro elemento existente em vez do BODY, você terá que usar document.getElementById()e / ou document.getElementsByTagName(); é por isso que usei no exemplo.
Mathias Bynens
1
Além disso, seu código pode ficar muito confuso muito rapidamente se você adicionar / inserir "innerHTML" diretamente
James
1
@JimmyP: Que besteira! O próprio propósito desta questão é ser capaz de inserir HTML diretamente como strings, em vez de brincar com funções para construí-lo, atributo por atributo, nó por nó, elemento por elemento.
TheFlash
1
isso desanexa todos os manipuladores de eventos e pode causar grandes vazamentos de memória.
adardesign de
1

Que eu saiba, que, para ser justo, é bastante novo e limitado, o único problema potencial com essa técnica é o fato de que você é impedido de criar dinamicamente alguns elementos da tabela.

Eu uso um formulário para modelagem adicionando elementos de "modelo" a um DIV oculto e, em seguida, usando cloneNode (true) para criar um clone e anexá-lo conforme necessário. Tenha em mente que você precisa se certificar de reatribuir os IDs conforme necessário para evitar duplicação.

Rpc
fonte
-1

Como outros disseram, a conveniente funcionalidade jQuery prepend pode ser emulada:

var html = '<div>Hello prepended</div>';
document.body.innerHTML = html + document.body.innerHTML;

Embora alguns digam que é melhor não "bagunçar" o innerHTML , ele é confiável em muitos casos de uso, se você souber disso:

Se um <div>, <span>ou <noembed>nó tem um nó filho de texto que inclui os personagens ( &), ( <) ou ( >), innerHTML retorna estes caracteres como &amp, &lte &gtrespectivamente. Use Node.textContentpara obter uma cópia correta do conteúdo desses nós de texto.

https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML

Ou:

var html = '<div>Hello prepended</div>';
document.body.insertAdjacentHTML('afterbegin', html)

insertAdjacentHTMLprovavelmente é uma boa alternativa: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

taseenb
fonte
-2

Se você deseja inserir o código HTML dentro da tag da página existente, use o Jnerator . Esta ferramenta foi criada especialmente para este fim.

Em vez de escrever o próximo código

    var htmlCode = '<ul class=\'menu-countries\'><li
        class=\'item\'><img src=\'au.png\'></img><span>Australia </span></li><li
        class=\'item\'><img src=\'br.png\'> </img><span>Brazil</span></li><li
        class=\'item\'> <img src=\'ca.png\'></img><span>Canada</span></li></ul>';
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;

Você pode escrever uma estrutura mais compreensível

    var jtag = $j.ul({
        class: 'menu-countries',
        child: [
            $j.li({ class: 'item', child: [
                $j.img({ src: 'au.png' }),
                $j.span({ child: 'Australia' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'br.png' }),
                $j.span({ child: 'Brazil' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'ca.png' }),
                $j.span({ child: 'Canada' })
            ]})
        ]
    });
    var htmlCode = jtag.html();
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;
Berezh
fonte