jquery:самая быстрая вставка DOM?
-
02-07-2019 - |
Вопрос
У меня появилось плохое предчувствие по поводу того, как я вставляю большие объемы HTML.Давайте предположим, что мы получили:
var html="<table>..<a-lot-of-other-tags />..</table>"
и я хочу вложить это в
$("#mydiv")
раньше я делал что-то вроде
var html_obj = $(html);
$("#mydiv").append(html_obj);
Правильно ли, что jQuery выполняет синтаксический анализ html
для создания DOM-объектов?Ну, это то, что я где-то читал (ОБНОВЛЕНИЕ: Я имел в виду, что я читал, jQuery анализирует html для создания всего DOM-дерева вручную - это бессмыслица, не так ли?!), поэтому я изменил свой код:
$("#mydiv").attr("innerHTML", $("#mydiv").attr("innerHTML") + html);
По ощущениям быстрее, не так ли?И правильно ли, что это эквивалентно:
document.getElementById("mydiv").innerHTML += html
?или jquery делает какие-то дополнительные дорогостоящие вещи в фоновом режиме?
Хотелось бы также изучить альтернативные варианты.
Решение
innerHTML работает удивительно быстро, и во многих случаях вы получите наилучшие результаты, просто установив это (я бы просто использовал append).
Однако, если в "mydiv" уже много чего есть, вы заставляете браузер снова анализировать и отображать весь этот контент (все, что было там раньше, плюс весь ваш новый контент). Вы можете избежать этого, добавив вместо этого фрагмент документа в "mydiv":
var frag = document.createDocumentFragment();
frag.innerHTML = html;
$("#mydiv").append(frag);
Таким образом, анализируется только ваш новый контент (это неизбежно), а существующий контент - нет.
Редактировать:Я виноват...Я обнаружил, что innerHTML недостаточно хорошо поддерживается во фрагментах документа.Вы можете использовать тот же метод с любым типом узла.Для вашего примера вы могли бы создать узел корневой таблицы и вставить в него innerHTML:
var frag = document.createElement('table');
frag.innerHTML = tableInnerHtml;
$("#mydiv").append(frag);
Другие советы
Чего вы пытаетесь избежать?"Плохое предчувствие" - это невероятно расплывчато.Если вы услышали "DOM работает медленно" и решили "избежать DOM", то это невозможно.Любой метод вставки кода на страницу, включая innerHTML, приведет к созданию объектов DOM.DOM - это представление документа в памяти вашего браузера.Ты хотеть Объекты DOM, которые необходимо создать.
Причина, по которой люди говорят "DOM работает медленно", заключается в том, что создание элементов с document.createElement()
, который является официальным интерфейсом DOM для создания элементов, работает медленнее, чем использование нестандартного свойства innerHTML в некоторых браузерах.Это не означает, что создавать DOM-объекты плохо, это необходимый создавать объекты DOM, иначе ваш код вообще ничего бы не делал.
Ответ об использовании фрагмента DOM находится на правильном пути.Если у вас есть куча html-объектов, которые вы постоянно вставляете в DOM, то вы увидите некоторые улучшения скорости использования фрагмента.Этот пост Джона Ресига объясняет это довольно хорошо:http://ejohn.org/blog/dom-documentfragments/
Самый быстрый способ добавления элементов
Самый быстрый способ добавить к дереву DOM - это поместить все ваши добавления в буфер в одном фрагменте DOM, а затем добавить фрагмент dom к dom.
Это метод, который я использую в своем игровом движке.
//Returns a new Buffer object
function Buffer() {
//the framgment
var domFragment = document.createDocumentFragment();
//Adds a node to the dom fragment
function add(node) {
domFragment.appendChild(node);
}
//Flushes the buffer to a node
function flush(targetNode) {
//if the target node is not given then use the body
var targetNode = targetNode || document.body;
//append the domFragment to the target
targetNode.appendChild(domFragment);
}
//return the buffer
return {
"add": add,
"flush": flush
}
}
//to make a buffer do this
var buffer = Buffer();
//to add elements to the buffer do the following
buffer.add(someNode1);
//continue to add elements to the buffer
buffer.add(someNode2);
buffer.add(someNode3);
buffer.add(someNode4);
buffer.add(someN...);
//when you are done adding nodes flush the nodes to the containing div in the dom
buffer.flush(myContainerNode);
Используя этот объект, я могу отображать ~ 1000 элементов на экране ~ 40 раз в секунду в firefox 4.
Вот пример использования.
Для начала напишите сценарий, умножающий время, необходимое для выполнения этого действия, на 100 или 1000 раз с каждым методом.
Чтобы убедиться, что повторы каким-то образом не оптимизированы - я не эксперт в движках JavaScript - меняйте html, который вы вставляете каждый раз, скажем, помещая '0001', затем '0002', затем '0003' в определенную ячейку таблицы.
Я создаю гигантскую строку с помощью, а затем добавляю эту строку с помощью jquery.По-моему, работает хорошо и быстро.
Вы упомянули, что вас интересуют альтернативы.Если вы посмотрите на список Плагины jQuery, связанные с DOM вы найдете несколько, предназначенных для программной генерации DOM-деревьев.Смотрите, например Суперфлайдом или Создатель элементов DOM;но есть и другие.