#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:
- Сложно вставить несколько родственных узлов между другими родственными узлами. Чтобы сделать это, вы в конечном итоге вставляете HTML в какой-либо другой элемент (например, div), а затем перемещаете созданные элементы в DOM. К сожалению, вы не можете использовать DocumentFragment для этого, поэтому требуется перебор дочерних узлов
- Его использование в таблицах может быть проблематичным, IE не любит изменять innerHTML различных элементов в таблице, отличной от TD
- Браузеры генерируют различный HTML как свойство innerHTML, поэтому использовать его для сериализации элементов проблематично
- Использование свойства 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 элементов, так что на самом деле это составляет большой кусок.