Tworzenie nowego elementu DOM Z ciągu HTML przy użyciu wbudowanych metod DOM lub prototypu

Mam łańcuch HTML reprezentujący element: '<li>text</li>'. Chciałbym dołączyć go do elementu w DOM (a ul w moim przypadku). Jak mogę to zrobić za pomocą metod prototype lub DOM?

(wiem, że mógłbym to zrobić łatwo w jQuery, ale niestety nie używamy jQuery.)

Author: Just a student, 2009-01-30

21 answers

Uwaga: większość obecnych przeglądarek obsługuje elementy HTML <template>, które zapewniają bardziej niezawodny sposób przekształcania elementów z łańcuchów. Zobacz odpowiedź Marka Amery ' ego poniżej, aby uzyskać szczegóły .

Dla starszych przeglądarek i node / jsdom: (który nie obsługuje jeszcze elementów <template> w momencie pisania), użyj następującej metody. To samo robią biblioteki, aby uzyskać elementy DOM z ciągu HTML (z jakąś dodatkową pracą dla IE wokół błędów z jego implementacją innerHTML):

function createElementFromHTML(htmlString) {
  var div = document.createElement('div');
  div.innerHTML = htmlString.trim();

  // Change this to div.childNodes to support multiple top-level nodes
  return div.firstChild; 
}

Zauważ, że w przeciwieństwie do szablonów HTML ten nie będzie działał dla niektórych elementów, które zgodnie z prawem nie mogą być dziećmi <div>, takich jak <td> s.

Jeśli już korzystasz z biblioteki, polecam trzymać się zatwierdzonej przez Bibliotekę metody tworzenia elementów z łańcuchów HTML:

 617
Author: Crescent Fresh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-18 13:35:11

HTML 5 wprowadził element <template>, który może być używany do tego celu (jak opisano obecnie w WHATWG spec i MDN docs ).

A {[1] } jest elementem HTML, który jest dozwolony dla każdego innego typu elementu jako dziecka. template posiada właściwość .content, do której można uzyskać dostęp za pomocą JavaScript, który wskazuje na DocumentFragment z zawartością szablonu. Oznacza to, że można przekonwertować łańcuch HTML na elementy DOM, ustawiając innerHTML z elementu <template>, następnie sięgając do Właściwości template'S .content.

Przykłady:

/**
 * @param {String} HTML representing a single element
 * @return {Element}
 */
function htmlToElement(html) {
    var template = document.createElement('template');
    html = html.trim(); // Never return a text node of whitespace as the result
    template.innerHTML = html;
    return template.content.firstChild;
}

var td = htmlToElement('<td>foo</td>'),
    div = htmlToElement('<div><span>nested</span> <span>stuff</span></div>');

/**
 * @param {String} HTML representing any number of sibling elements
 * @return {NodeList} 
 */
function htmlToElements(html) {
    var template = document.createElement('template');
    template.innerHTML = html;
    return template.content.childNodes;
}

var rows = htmlToElements('<tr><td>foo</td></tr><tr><td>bar</td></tr>');

Zauważ, że podobne podejścia, które używają innego elementu kontenera, takiego jak div nie do końca działa. HTML ma ograniczenia co do tego, jakie typy elementów mogą istnieć wewnątrz jakich innych typów elementów; na przykład, nie można umieścić td jako bezpośredniego potomka div. Powoduje to, że te elementy znikają, jeśli spróbujesz ustawić innerHTML z div, aby je zawierały. Ponieważ <template> s nie mają takiego ograniczenia dotyczące ich treści, wada ta nie ma zastosowania w przypadku korzystania z szablonu.

Jednak {[3] } nie jest obsługiwana w niektórych starych przeglądarkach. Od stycznia 2018, Mogę używać... szacunki 90% użytkowników na całym świecie korzysta z przeglądarki, która obsługuje template s . W szczególności żadna wersja Internet Explorera nie obsługuje ich; Microsoft nie zaimplementował obsługi template aż do wydania Edge.

Jeśli masz szczęście pisać kod, który jest skierowany tylko do użytkowników w nowoczesnych przeglądarkach, śmiało i korzystać z nich już teraz. W przeciwnym razie być może będziesz musiał poczekać chwilę, aż użytkownicy nadrobią zaległości.

 191
Author: Mark Amery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-11 21:42:49

Nowsze implementacje DOM mają range.createContextualFragment, który robi to, co chcesz w sposób niezależny od RAM.

Jest szeroko wspierany. Aby się jednak upewnić, sprawdź jego kompatybilność w tym samym łączu MDN, ponieważ będzie się zmieniać. Od maja 2017 jest to:
Feature         Chrome   Edge   Firefox(Gecko)  Internet Explorer   Opera   Safari
Basic support   (Yes)    (Yes)  (Yes)           11                  15.0    9.1.2
 24
Author: kojiro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-20 05:41:44

Użyj insertAdjacentHTML () . Działa ze wszystkimi aktualnymi przeglądarkami, nawet z IE11.

var mylist = document.getElementById('mylist');
mylist.insertAdjacentHTML('beforeend', '<li>third</li>');
<ul id="mylist">
 <li>first</li>
 <li>second</li>
</ul>
 24
Author: Christian d'Heureuse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-01 18:15:58

Heres prosty sposób na to:

String.prototype.toDOM=function(){
  var d=document
     ,i
     ,a=d.createElement("div")
     ,b=d.createDocumentFragment();
  a.innerHTML=this;
  while(i=a.firstChild)b.appendChild(i);
  return b;
};

var foo="<img src='//placekitten.com/100/100'>foo<i>bar</i>".toDOM();
document.body.appendChild(foo);
 15
Author: william malo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-03 00:02:50

Nie ma potrzeby żadnych poprawek, masz natywne API:

const toNodes = html =>
    new DOMParser().parseFromString(html, 'text/html').body.childNodes
 14
Author: math2001,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-24 21:48:41

Z Prototype, można również zrobić:

HTML:

<ul id="mylist"></ul>

JS:

$('mylist').insert('<li>text</li>');
 10
Author: Pablo Borowicz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-07 11:49:48

Dla niektórych fragmentów html, takich jak <td>test</td>, div.innerHTML, DOMParser.parseFromString i range.createContextualFragment (bez odpowiedniego kontekstu) nie utworzy elementu <td>.

JQuery.parseHTML () obsługuje je (wyodrębniłem funkcję parseHTML jQuery 2 do niezależnego gist ).

Dla Edge 13+ użyj znacznika szablonu:

function parseHTML(html) {
    var t = document.createElement('template');
        t.innerHTML = html;
    return t.content.cloneNode(true);
}

var documentFragment = parseHTML('<td>Test</td>');
 8
Author: Munawwar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-16 20:27:26

Możesz utworzyć poprawne węzły DOM z ciągu znaków używając:

document.createRange().createContextualFragment()

Poniższy przykład dodaje element przycisku na stronie pobierający znaczniki z ciągu znaków:

let html = '<button type="button">Click Me!</button>';
let fragmentFromString = function (strHTML) {
  return document.createRange().createContextualFragment(strHTML);
}
let fragment = fragmentFromString(html);
document.body.appendChild(fragment);
 5
Author: GibboK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-20 05:27:35

Używam tej metody (działa w IE9+), chociaż nie będzie ona analizować <td> ani innych nieprawidłowych bezpośrednich potomków ciała:

function stringToEl(string) {
    var parser = new DOMParser(),
        content = 'text/html',
        DOM = parser.parseFromString(string, content);

    // return element
    return DOM.body.childNodes[0];
}

stringToEl('<li>text</li>'); //OUTPUT: <li>text</li>
 4
Author: usrbowe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-08 13:08:16

Dodałem Document prototyp, który tworzy element z łańcucha:

Document.prototype.createElementFromString = function (str) {
    const element = new DOMParser().parseFromString(str, 'text/html');
    const child = element.documentElement.querySelector('body').firstChild;
    return child;
};
 3
Author: Raza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-20 17:24:20

Oto Mój kod i działa:

function parseTableHtml(s) { // s is string
    var div = document.createElement('table');
    div.innerHTML = s;

    var tr = div.getElementsByTagName('tr');
    // ...
}
 2
Author: Wen Qi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-21 07:40:44

Późno, ale tylko jako notka;

Możliwe jest dodanie trywialnego elementu do elementu docelowego jako kontenera i usunięcie go po użyciu.

// testowane na chrome 23.0, firefox 18.0, ie 7-8-9 i operze 12.11.

<div id="div"></div>

<script>
window.onload = function() {
    var foo, targetElement = document.getElementById('div')
    foo = document.createElement('foo')
    foo.innerHTML = '<a href="#" target="_self">Text of A 1.</a> '+
                    '<a href="#" onclick="return !!alert(this.innerHTML)">Text of <b>A 2</b>.</a> '+
                    '<hr size="1" />'
    // Append 'foo' element to target element
    targetElement.appendChild(foo)

    // Add event
    foo.firstChild.onclick = function() { return !!alert(this.target) }

    while (foo.firstChild) {
        // Also removes child nodes from 'foo'
        targetElement.insertBefore(foo.firstChild, foo)
    }
    // Remove 'foo' element from target element
    targetElement.removeChild(foo)
}
</script>
 2
Author: K-Gun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-13 12:39:13

HTML5 & ES6

Demo

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @description HTML5 Template
 * @augments
 * @example
 *
 */

/*

<template>
    <h2>Flower</h2>
    <img src="https://www.w3schools.com/tags/img_white_flower.jpg">
</template>


<template>
    <div class="myClass">I like: </div>
</template>

*/

const showContent = () => {
    // let temp = document.getElementsByTagName("template")[0],
    let temp = document.querySelector(`[data-tempalte="tempalte-img"]`),
        clone = temp.content.cloneNode(true);
    document.body.appendChild(clone);
};

const templateGenerator = (datas = [], debug = false) => {
    let result = ``;
    // let temp = document.getElementsByTagName("template")[1],
    let temp = document.querySelector(`[data-tempalte="tempalte-links"]`),
        item = temp.content.querySelector("div");
    for (let i = 0; i < datas.length; i++) {
        let a = document.importNode(item, true);
        a.textContent += datas[i];
        document.body.appendChild(a);
    }
    return result;
};

const arr = ["Audi", "BMW", "Ford", "Honda", "Jaguar", "Nissan"];

if (document.createElement("template").content) {
    console.log("YES! The browser supports the template element");
    templateGenerator(arr);
    setTimeout(() => {
        showContent();
    }, 0);
} else {
    console.error("No! The browser does not support the template element");
}
@charset "UTf-8";

/* test.css */

:root {
    --cololr: #000;
    --default-cololr: #fff;
    --new-cololr: #0f0;
}

[data-class="links"] {
    color: white;
    background-color: DodgerBlue;
    padding: 20px;
    text-align: center;
    margin: 10px;
}
<!DOCTYPE html>
<html lang="zh-Hans">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Template Test</title>
    <!--[if lt IE 9]>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
    <![endif]-->
</head>

<body>
    <section>
        <h1>Template Test</h1>
    </section>
    <template data-tempalte="tempalte-img">
        <h3>Flower Image</h3>
        <img src="https://www.w3schools.com/tags/img_white_flower.jpg">
    </template>
    <template data-tempalte="tempalte-links">
        <h3>links</h3>
        <div data-class="links">I like: </div>
    </template>
    <!-- js -->
</body>

</html>
 1
Author: xgqfrms-gildata,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-28 11:45:50

Do diabła z tym pomyślałem, że podzielę się tym skomplikowanym, ale prostym podejściem, które wymyśliłem... Może ktoś znajdzie coś użytecznego.

/*Creates a new element - By Jamin Szczesny*/
function _new(args){
    ele = document.createElement(args.node);
    delete args.node;
    for(x in args){ 
        if(typeof ele[x]==='string'){
            ele[x] = args[x];
        }else{
            ele.setAttribute(x, args[x]);
        }
    }
    return ele;
}

/*You would 'simply' use it like this*/

$('body')[0].appendChild(_new({
    node:'div',
    id:'my-div',
    style:'position:absolute; left:100px; top:100px;'+
          'width:100px; height:100px; border:2px solid red;'+
          'cursor:pointer; background-color:HoneyDew',
    innerHTML:'My newly created div element!',
    value:'for example only',
    onclick:"alert('yay')"
}));
 0
Author: JxAxMxIxN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-21 03:47:51

W celu zwiększenia przydatności .toDOM () snippet, który możemy znaleźć w różnych miejscach, możemy teraz bezpiecznie używać backticks (literały szablonów ).

Więc możemy mieć pojedyncze i podwójne cudzysłowy w foo deklaracji html.

To zachowuje się jak heredocs dla tych, którzy znają ten termin.

Można to dodatkowo wzbogacić o zmienne, aby stworzyć złożony szablon:

Literały szablonów to / align = "left" / () ( grave accent) znak zamiast podwójnych lub pojedynczych cudzysłowów. Literały szablonów mogą zawiera symbole zastępcze. Są one oznaczone znakiem dolara i kręcone klamry (${wyrażenie}). Wyrażenia w miejscach zastępczych i tekst między nimi jest przekazywany do funkcji. Domyślna funkcja po prostu łączy części w jeden ciąg. Jeśli istnieje wyrażenie poprzedzający szablon literal (tag tutaj), nazywa się to " tagged szablon". W takim przypadku wyrażenie znacznika (Zwykle funkcja) otrzymuje wywołany z przetworzonym szablonem, który można następnie manipulować przed wyjściem. Aby uniknąć cofnięcia w szablonie literalnie, umieść ukośnik wsteczny \ przed tyknięciem wstecznym.

String.prototype.toDOM=function(){
  var d=document,i
     ,a=d.createElement("div")
     ,b=d.createDocumentFragment()
  a.innerHTML = this
  while(i=a.firstChild)b.appendChild(i)
  return b
}

// Using template litterals
var a = 10, b = 5
var foo=`
<img 
  onclick="alert('The future start today!')"   
  src='//placekitten.com/100/100'>
foo${a + b}
  <i>bar</i>
    <hr>`.toDOM();
document.body.appendChild(foo);
img {cursor: crosshair}

Https://caniuse.com/template-literals

 0
Author: Cryptopat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-17 20:41:02
function domify (str) {
  var el = document.createElement('div');
  el.innerHTML = str;

  var frag = document.createDocumentFragment();
  return frag.appendChild(el.removeChild(el.firstChild));
}

var str = "<div class='foo'>foo</div>";
domify(str);
 -1
Author: Denim Demon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-08 10:59:21

Oto działający kod dla mnie

Chciałem przekonwertować łańcuch' Text ' na element HTML

var diva = UWA.createElement('div');
diva.innerHTML = '<a href="http://wwww.example.com">Text</a>';
var aelement = diva.firstChild;
 -1
Author: Sandeep Badawe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-08 10:23:19
var jtag = $j.li({ child:'text' }); // Represents: <li>text</li>
var htmlContent = $('mylist').html();
$('mylist').html(htmlContent + jtag.html());

Użyj jnerator

 -2
Author: Berezh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-25 00:39:23

Możesz użyć następującej funkcji, aby przekonwertować tekst "HTML" na element

function htmlToElement(html)
{
  var element = document.createElement('div');
  element.innerHTML = html;
  return(element);
}
var html="<li>text and html</li>";
var e=htmlToElement(html);
 -2
Author: Saeed saeeyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-11 06:05:22

To też zadziała:

$('<li>').text('hello').appendTo('#mylist');

To bardziej przypomina jQuery z wywołaniami funkcji łańcuchowych.

 -5
Author: jack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-11 22:02:29