Добавление строки HTML в DOM


121

Как добавить эту HTML-строку

var str = '<p>Just some <span>text</span> here</p>';

в DIV с идентификатором, 'test'который находится в DOM?

(Кстати, div.innerHTML += str;это не приемлемо.)

Ответы:


243

Используйте, insertAdjacentHTMLесли он доступен, в противном случае используйте какой-то запасной вариант. insertAdjacentHTML поддерживается во всех текущих браузерах .

div.insertAdjacentHTML( 'beforeend', str );

Живая демонстрация: http://jsfiddle.net/euQ5n/


1
@alex Это та же концепция: парсинг HTML-строки и помещение ее в DOM. Но функциональность другая - innerHTMLпомещает строку в элемент (заменяя всех дочерних элементов), тогда как insertAdjacentHTMLпомещает ее (1) перед элементом, (2) после элемента, (3) внутри элемента перед первым дочерним элементом или (4) внутри элемента после последнего дочернего элемента.
— Шиме Видас,

3
@alex insertAdjacentHTMLбыстрее, чем добавление к innerHTML, потому insertAdjacentHTMLчто не сериализует и не повторно анализирует существующие дочерние элементы элемента.
— hsivonen

2
Кроме того, insertAdjacentHTMLсохраняет значения измененных элементов формы, тогда как добавление к innerHTMLперестраивает элемент и теряет весь контекст формы.
— Брэндон Гано,

20

Это приемлемо?

var child = document.createElement('div');
child.innerHTML = str;
child = child.firstChild;
document.getElementById('test').appendChild(child);

jsFiddle .

Но , ответ Нила является лучшим решением.


1
@ Šime Работа с DOM API всегда кажется хакерской: P Вы бы предпочли десериализовать строку без нее innerHTML?
— Alex

Что ж, да, если есть другой способ использовать анализатор HTML в браузере, я хотел бы знать ...
— Шиме Видас

1
@ Šime - Я думаю, что есть только два способа использовать HTML-парсер браузера, innerHTML и document.write. И если вы думаете, что innerHTML - это взлом ...
— Алохи

@Alohci Там является еще один способ: insertAdjacentHTML.
— Шиме Видас,

1
@ Šime -Спасибо. Нашел версию WHATWG. Это находится в спецификации DOM Parsing and Serialization . Это указывает на то, что, помимо innerHTML и insertAdjacentHTML, есть outerHTML и, я думаю, createContextualFragment.
— Alohci

16

Производительность

AppendChild(E) более чем в 2 раза быстрее, чем другие решения для Chrome и Safari, insertAdjacentHTML(F) является самым быстрым в firefox. innerHTML=(B) (не путать с +=(А)) является вторым быстрым решением во всех браузерах , и это гораздо удобнее , чем Е и F.

подробности

Настройка среды (2019.07.10) MacOs High Sierra 10.13.4 в Chrome 75.0.3770 (64-разрядная версия), Safari 11.1.0 (13604.5.6), Firefox 67.0.0 (64-разрядная версия)

введите описание изображения здесь

  • в Chrome E (140 тыс. операций в секунду) - самый быстрый, B (47k) и F (46k) - второй, A (332) - самый медленный
  • в firefox F (94k) самый быстрый, затем B (80k), D (73k), E (64k), C (21k) самый медленный - A (466)
  • в Safari E (207k) самый быстрый, затем B (89k), F (88k), D (83k), C (25k), самый медленный - A (509)

Вы можете воспроизвести тест на своей машине здесь


12

Идея состоит в том, чтобы использовать innerHTMLпромежуточный элемент, а затем переместить все его дочерние узлы туда, где они действительно нужны appendChild.

var target = document.getElementById('test');
var str = '<p>Just some <span>text</span> here</p>';

var temp = document.createElement('div');
temp.innerHTML = str;
while (temp.firstChild) {
  target.appendChild(temp.firstChild);
}

Это позволяет избежать уничтожения любых обработчиков событий, div#testно по-прежнему позволяет добавлять строку HTML.


3

Правильный способ - использовать insertAdjacentHTML. В Firefox ранее 8 вы можете вернуться к использованию, Range.createContextualFragmentесли ваш тег strне содержит scriptтегов.

Если у вас strесть scriptтеги, вам необходимо удалить scriptэлементы из фрагмента, возвращаемого createContextualFragmentперед вставкой фрагмента. В противном случае скрипты запустятся. ( insertAdjacentHTMLотмечает скрипты как невыполнимые.)


Спасибо за упоминание createContextualFragment . Я искал способ сделать некоторые html-включения со сценариями, запускаемыми только в том случае, если пользователь соглашается установить cookie.
— Schliflo

3

Быстрый взлом :


<script>
document.children[0].innerHTML="<h1>QUICK_HACK</h1>";
</script>

Случаи использования :

1: Сохраните как файл .html и запустите в Chrome, Firefox или Edge. (IE не работает)

2: использовать в http://js.do

В действии: http://js.do/HeavyMetalCookies/quick_hack

Разбитые с комментариями:

<script>

//: The message "QUICK_HACK" 
//: wrapped in a header #1 tag.
var text = "<h1>QUICK_HACK</h1>";

//: It's a quick hack, so I don't
//: care where it goes on the document,
//: just as long as I can see it.
//: Since I am doing this quick hack in
//: an empty file or scratchpad, 
//: it should be visible.
var child = document.children[0];

//: Set the html content of your child
//: to the message you want to see on screen.
child.innerHTML = text;

</script>

Причина, по которой я опубликовал:

У JS.do есть два обязательных элемента:

  1. Без автозаполнения
  2. Вертикальный монитор дружественный

Но не показывает сообщения console.log. Пришел сюда в поисках быстрого решения. Я просто хочу увидеть результаты нескольких строк кода блокнота, другие решения требуют слишком много работы.


1

Почему это неприемлемо?

document.getElementById('test').innerHTML += str

было бы учебным способом сделать это.


4
Однако это убило бы обработчики событий, прикрепленные к #test. Обычно это нежелательно.
— Alex

Интересно, что он это делает. На самом деле это не кажется логичным.
— Ник Брант,

2
Думаю, это логично, если вы подумаете о сериализации HTML в строку, а затем вернете HTML обратно.
— Alex

Я предполагаю, что для сброса обработчика событий придется снова запустить JavaScript. Справедливо.
— Ник Брант,

1
@Nick Вы не хотите структурировать (сериализовать) часть DOM только для того, чтобы вы могли объединить ее с другой строкой, а затем проанализировать все это обратно в DOM. Как сказал Алексей, сериализация не будет записывать связанные обработчики событий (среди прочего). Даже если бы сериализация могла захватить все, вы все равно не захотели бы этого делать.
— Шиме Видас,

0

Это может решить

 document.getElementById("list-input-email").insertAdjacentHTML('beforeend', '<div class=""><input type="text" name="" value="" class="" /></div>');

3
Добро пожаловать в Stack overflow. Пожалуйста, объясните свой код как часть ответа, чтобы предоставить некоторый контекст, а не просто вставлять длинную единственную строку кода. Хотя вы это понимаете, другие могут не понять, что он делает.
— credit.burger 07

0

InnerHTML очищает все данные, такие как событие, для существующих узлов

append child с firstChild добавляет только первого ребенка в innerHTML. Например, если нам нужно добавить:

 <p>text1</p><p>text2</p>

будет отображаться только text1

Как насчет этого:

добавляет специальный тег в innerHTML, добавляя дочерний элемент, а затем редактирует внешний HTML, удаляя созданный нами тег. Не знаю, насколько это умно, но у меня это работает, или вы можете изменить externalHTML на innerHTML, чтобы не использовать замену функции

function append(element, str)
{

  var child = document.createElement('someshittyuniquetag');
		
  child.innerHTML = str;

  element.appendChild(child);

  child.outerHTML = child.outerHTML.replace(/<\/?someshittyuniquetag>/, '');

// or Even child.outerHTML = child.innerHTML


  
}
<div id="testit">
This text is inside the div
<button onclick="append(document.getElementById('testit'), '<button>dadasasdas</button>')">To div</button>
<button onclick="append(this, 'some text')">to this</button>
</div>


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.