Добавление элементов в виде строки против createElement()

#javascript #performance #innerhtml #createelement

#javascript #Производительность #innerhtml #createelement

Вопрос:

Для того, чего я хочу достичь, я могу использовать либо createElement() , либо innerHTML и строку.

Что в итоге действительно быстрее? Долгое время меня убеждали, что строки работают намного медленнее, чем встроенные функции, которые возвращают те же результаты, но действительно ли это так?

Я спрашиваю, потому что я пробовал createElement() и кажется, что все свойства, которые должны быть добавлены к каждому элементу, замедляют работу. Не только это, но и занимает больше места. У меня есть цикл, который простирается от 1 до бесконечности в зависимости от длины массива, хотя предпочтительно добавлять до 50 или около того элементов, прежде чем появятся признаки замедления. Внутри этих примерно 50 элементов, которые я хочу создать, находится еще около 10 элементов. Итак, в целом, фактически создается около 500 элементов.

Я заметил некоторое замедление быстрее, чем обычно, при создании элементов со встроенными функциями, и из-за того, что я дурачился с сбросом этого массива (массив был 5D и не был установлен в том же скрипте), я хотел бы знать, что действительно лучше, как с точки зрения скорости, так и просто лучшей практики, прежде чем делать это снова.

Комментарии:

1. возможно, вам следует создать обе версии и проверить, какая из них самая быстрая

2. Я сомневаюсь, что в любом случае будет большая разница в производительности. Я бы рекомендовал выбрать тот подход, который вам проще всего кодировать и поддерживать. Общее эмпирическое правило, которое я использую, заключается в том, что для незначительных изменений (обновление текста, добавление ссылки и т.д.) Используйте innerHTML , А для серьезных изменений (добавление множества ссылок или компонентов в один контейнер или любую структуру глубиной более 2 узлов) используйте createElement() .

3. Очень интересный вопрос, и я хотел бы найти несколько реальных тестов.. Я видел js-виджеты, которые при загрузке увлажняют довольно большие вложенные структуры createElement данными json вместо использования предварительно загруженных (и скрытых) html-шаблонов для прямого дублирования. Но даже это, вероятно, привело бы к потере innerHTML в виде списка, состоящего, скажем, из нескольких сотен элементов

Ответ №1:

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

По моему собственному опыту, я помню только один случай, когда мне действительно понадобилось внести большие изменения в большую веб-страницу, в частности, перестроить элемент таблицы, который содержал сотни или потенциально тысячи строк, в каждой из которых было много ячеек, и я обнаружил, что создание строковой переменной и последующая установка innerHTML один раз в конце было намного, намного быстрее, чем пытаться сделать это с помощью функций DOM. Но это было для конкретного веб-приложения для интрасети, где было гарантировано, что 100% пользователей будут в IE, поэтому мне не нужно было беспокоиться о кроссбраузерном тестировании.

Даже если вы решите пойти по пути построения строк, существуют разные мнения о том, как это ускорить. Я прочитал не одну статью, в которой сравнивалась производительность непрерывного добавления в конец вашей строки (стандартные myString = 'something' 'something else' операции типа) с добавлением в конец переменной массива и последующим использованием Array.join() для создания одной большой строки в конце. Опять же, это имело большое значение для определенных версий некоторых браузеров, но не отличалось или было хуже в других.

Комментарии:

1. Как ни странно, это был самый точный ответ, потому что, похоже, верно, что разные браузеры на самом деле выполняют одно быстрее другого. IE, по-видимому, обрабатывает строки намного лучше, но Google Chrome обрабатывает методы DOM невероятно быстро по сравнению с innerHTML.

Ответ №2:

innerHTML имеет смысл, если у вас есть большие куски содержимого для добавления или заполнения существующего элемента.

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

Есть некоторые оговорки к использованию innerHTML:

  1. Сложно вставить несколько родственных узлов между другими родственными узлами. Чтобы сделать это, вы в конечном итоге вставляете HTML в какой-либо другой элемент (например, div), а затем перемещаете созданные элементы в DOM. К сожалению, вы не можете использовать DocumentFragment для этого, поэтому требуется перебор дочерних узлов
  2. Его использование в таблицах может быть проблематичным, IE не любит изменять innerHTML различных элементов в таблице, отличной от TD
  3. Браузеры генерируют различный HTML как свойство innerHTML, поэтому использовать его для сериализации элементов проблематично
  4. Использование свойства innerHTML может привести к удалению прослушивателей других элементов, даже если они не были изменены innerHTML

например

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

<!-- Button to add a click listener to above div -->
<button onclick="
  var el = document.getElementById('div0');
  el.onclick = function(){alert(this.id);}
">Add listener as property</button>

<!-- Button to modify the body's innerHTML -->
<button onclick="
  var body = document.getElementsByTagName('body')[0];
  body.innerHTML  = '';
">Append to body.innerHTML</button>
  

Вы можете нажать на первую кнопку, чтобы добавить прослушиватель кликов в div0, но когда вы нажимаете на вторую кнопку (которая, кажется, ничего не делает, но на самом деле сбрасывает innerHTML), прослушиватель удаляется.

Ответ №3:

Я думаю, вы частично ответили на свой собственный вопрос.

На скорость это действительно не влияет, если только вы не хотите вставить очень большой фрагмент html с помощью innerHTML. использование createElement более «дружелюбно к DOM», но в итоге вы получаете намного больше строк кода, чтобы иногда вносить небольшие изменения.

Лично я использую innerHTML или что угодно, что jQuery использует с .html() свойством. но когда мне приходится использовать циклы для выполнения сложной работы, я использую элемент create.

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

Комментарии:

1. С jQuery нет необходимости использовать html() elementX.append($('<span>this works as expected</span>')).click(...)

2. Это интересно, я не знал, что вы можете получить доступ к своей строке так быстро.

3. Я добавил немного информации в OP несколько минут назад. Я сделал так, чтобы это звучало как немного, но каждый элемент, который я добавлял в цикл, также содержал около 10 элементов, так что на самом деле это составляет большой кусок.