Создание нового элемента DOM из строки HTML с использованием встроенных методов DOM или Prototype - PullRequest
501 голосов
/ 30 января 2009

У меня есть HTML-строка, представляющая элемент: '<li>text</li>'. Я хотел бы добавить его к элементу в DOM (ul в моем случае). Как я могу сделать это с помощью Prototype или DOM?

(я знаю, что мог бы легко это сделать в jQuery, но, к сожалению, мы не используем jQuery.)

Ответы [ 22 ]

698 голосов
/ 30 января 2009

Примечание: большинство современных браузеров поддерживают элементы HTML <template>, которые обеспечивают более надежный способ превращения создания элементов из строк. Подробнее см. Марк Эмери ниже .

Для более старых браузеров и node / jsdom : (который еще не поддерживает <template> элементов на момент написания), используйте следующий метод. Это то же самое, что библиотеки используют для получения элементов DOM из строки HTML ( с некоторой дополнительной работой для IE для обхода ошибок с его реализацией 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; 
}

Обратите внимание, что в отличие от шаблонов HTML это не будет работать для некоторых элементов, которые по закону не могут быть дочерними по отношению к <div>, например <td> s.

Если вы уже используете библиотеку, я бы порекомендовал вам придерживаться одобренного библиотекой метода создания элементов из строк HTML:

242 голосов
/ 14 февраля 2016

HTML 5 представил элемент <template>, который можно использовать для этой цели (как теперь описано в спецификациях WhatWG и MDN ).

A <template> - это HTML-элемент, который допускается для любого другого типа элемента в качестве дочернего. У template есть свойство .content, к которому вы можете обратиться с помощью JavaScript, что указывает на DocumentFragment с содержимым шаблона. Это означает, что вы можете преобразовать строку HTML в элементы DOM, установив innerHTML элемента <template>, а затем перейдя в свойство template '.content.

Примеры:

/**
 * @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>');

Обратите внимание, что подобные подходы, в которых использует другой элемент контейнера, такой как div, не совсем работают. HTML имеет ограничения на то, какие типы элементов могут существовать внутри каких других типов элементов; например, вы не можете поставить td как прямой потомок div. Это приводит к исчезновению этих элементов, если вы попытаетесь установить innerHTML из div, чтобы они содержались. Поскольку <template> s не имеют таких ограничений на их содержимое, этот недостаток не применяется при использовании шаблона.

Однако template не поддерживается в некоторых старых браузерах. По состоянию на январь 2018 года Могу ли я использовать ... оценки 90% пользователей во всем мире используют браузер, который поддерживает template s . В частности, ни одна версия Internet Explorer не поддерживает их; Microsoft не реализовала поддержку template до выхода Edge.

Если вам посчастливилось писать код, предназначенный только для пользователей в современных браузерах, используйте его прямо сейчас. В противном случае вам, возможно, придется подождать некоторое время, чтобы пользователи наверстали упущенное.

63 голосов
/ 29 октября 2017

Использовать insertAdjacentHTML () . Он работает со всеми современными браузерами, даже с IE11.

var mylist = document.getElementById('mylist');
mylist.insertAdjacentHTML('beforeend', '<li>third</li>');
<ul id="mylist">
 <li>first</li>
 <li>second</li>
</ul>
25 голосов
/ 07 сентября 2011

Более новые реализации DOM имеют range.createContextualFragment, что делает то, что вы хотите, независимо от фреймворка.

Это широко поддерживается. Однако, чтобы быть уверенным, проверьте его совместимость в той же ссылке MDN, поскольку она будет меняться. По состоянию на май 2017 года это так:

Feature         Chrome   Edge   Firefox(Gecko)  Internet Explorer   Opera   Safari
Basic support   (Yes)    (Yes)  (Yes)           11                  15.0    9.1.2
16 голосов
/ 25 февраля 2017

Никаких настроек не требуется, у вас есть собственный API:

const toNodes = html =>
    new DOMParser().parseFromString(html, 'text/html').body.childNodes
15 голосов
/ 03 мая 2013

Вот простой способ сделать это:

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);
11 голосов
/ 17 декабря 2015

Для некоторых html-фрагментов, таких как <td>test</td>, div.innerHTML, DOMParser.parseFromString и range.createContextualFragment (без правильного контекста), упомянутых в других ответах, не будет создаваться элемент <td>.

jQuery.parseHTML () обрабатывает их правильно (я извлек функцию jQuery 2 parseHTML в независимую функцию , которая может использоваться в кодовых базах не-jquery).

Если вы поддерживаете только Edge 13+, проще использовать тег шаблона HTML5:

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

var documentFragment = parseHTML('<td>Test</td>');
10 голосов
/ 19 февраля 2009

С Prototype вы также можете сделать:

HTML:

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

JS:

$('mylist').insert('<li>text</li>');
7 голосов
/ 28 февраля 2017

Вы можете создать действительные узлы DOM из строки, используя:

document.createRange().createContextualFragment()

В следующем примере добавляется элемент кнопки на странице, извлекающий разметку из строки:

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 голосов
/ 08 июня 2016

Я использую этот метод (работает в IE9 +), хотя он не будет анализировать <td> или некоторые другие недопустимые прямые дочерние элементы тела:

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...