Вопрос по dom-manipulation, jquery – Что лучше: создание html-строки или создание DOM-элемента jquery?

15

Хорошо, я переписываю некоторые ванильные функции JS в своем текущем проекте, и я нахожусь в точке, где генерируется много HTML-кода для всплывающих подсказок и т. Д.

Мой вопрос, лучше / предпочтительнее сделать это:

var html = '<div><span>Some More Stuff</span></div>';
if (someCondition) {
    html += '<div>Some Conditional Content</div>';
}
$('#parent').append(html);

ИЛИ ЖЕ

var html = $('<div/>').append($('<span/>').append('Some More Stuff'));
if (someCondition) {
    html.append($('<div/>').append('Some conditionalContent');
}
$('#parent').append(html);

?

Ваш Ответ

4   ответа
2

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

Я не использую innerHTML вообще ни в одном из примеров: речь идет о генерации с нуля, а не о прямых манипуляциях с существующими элементами. Это в значительной степени просто конкатенация строк против создания элементов. Ed James
Не знаю, полезная информация, но я инициализирую div во втором примере как пустые (которые, насколько я знаю, не будут использовать innerHTML?), И в первом примере я строю с нуля в строку, затем с помощью добавления (который я предполагаю, делает innerHTML, но только один раз). Ed James
@EdWoodcock$("<div>1 2 3</div>") использованияinnerHTML in implementation so yes you are using innerHTML`. cletus
Тестирование PPK показывает, что innerHTML быстрее (намного быстрее для IE), чем манипулирование DOM:quirksmode.org/dom/innerhtml.html Jeffery To
36

С точки зрения производительности:это зависит.

В вашем коротком примере быстрее добавить текст, поскольку вы фактически не создаете никаких элементов DOM до конца. Однако, если вы делаете этомногозатем добавляется время конкатенации строк в сравнении с производительностью фрагментов кэшированных документов.

Когда вы делаете$(html) JQuery кеширует это какфрагмент документа (при условии, что длина строки составляет 512 байт или меньше), хотя выигрыш при кешировании невелик$("<div />")... однако, если вы делаете это тысячи раз, это будет ощутимым эффектом: конкатенация строк становится более дорогой, а длина строки увеличивается, стоимость фрагмента кэшированного документа довольно стабильна.

Обновить: Вот несколько быстрых примеров, чтобы понять, что я имею в виду, используйте firebug, чтобы получить время консоли здесь:

Вы можете запустить это для себя:http://jsfiddle.net/Ps5ja/

console.time('concat');
var html = "";
for(var i = 0; i < 500; i++) {
    html += '<div><span>Some More Stuff</span></div>';
    html += '<div>Some Conditional Content</div>';
}
var elem = $(html);
console.timeEnd('concat'); //25ms

console.time('DOM');
var parent = $("<div />")
for(var j = 0; j < 500; j++) {
    parent.append($('<div/>').append($('<span/>', {text :'Some More Stuff'})));
    parent.append($('<div/>',{ text: 'Some conditionalContent' }));
}
console.timeEnd('DOM'); //149ms

console.time('concat caching');
var html = "";
for(var i = 0; i < 5000; i++)
    html += '<div><span>Some More Stuff</span></div><div>Some Conditional Content</div>';
var elem = $(html);
console.timeEnd('concat caching'); //282ms

console.time('DOM caching');
var parent = $("<div />")
for(var j = 0; j < 5000; j++)
    parent.append('<div><span>Some More Stuff</span></div><div>Some Conditional Content</div>');
console.timeEnd('DOM caching'); //157ms

Обратите вниманиеvar elem = $(html); в тесте строк мы создаем одни и те же элементы DOM, в противном случае вы сравниваете конкатенацию строк с фактическим созданием DOM, вряд ли это справедливое сравнение, и тоже не очень полезно :)

Из вышесказанного видно, что чем сложнее кэшированный фрагмент, тем больше влияние оказывает кэширование. В первом тесте, который является вашим примером без некоторого очищения условия, DOM проигрывает, потому что в этом тесте выполняется много небольших операций (на моей машине, но ваши отношения должны быть примерно одинаковыми):HTML контакт: 25 мс, DOM Manipulation: 149мс.

Однако, если вы можете кэшировать сложный фрагмент, вы получаете преимущество, заключающееся в том, что вы не создаете эти элементы DOM повторно, а просто клонируете их. Во втором тесте DOM выигрывает, потому что в то время как метод HTML создает эту коллекцию элементов DOM5000 раз, второй кэшированный метод только создает егоодин рази клонирует его 5000 раз. В этом тесте:HTML Concat: 282 мс, Манипуляция DOM: 157мс.

Я понимаю, что это ненепосредственно в ответ на ваш вопрос, но, основываясь на комментариях, кажется, что есть некоторое любопытство по поводу производительности, так что просто дайте что-то, что вы можете увидеть / протестировать / поиграть.

Не знаю, почему за это проголосовали. +1 от меня. cletus
Я могу только предположить, что downvoter мог бы посчитать это преждевременной оптимизацией? hippietrail
Люблю знать, почему понизили на этом. Человек не прав или нет? Просвети нас. Dave Markle
Договорились: почему понижение голоса, кажется мне довольно здравым аргументом. Я не делаю тысячи конкурсов, поэтому я думаю, что все будет в порядке. Вкратце, насколько мне известно, и Firefox, и Chrome в наши дни используют метод массива в стиле StringBuilder для конкатенации строк, поэтому конкататы строк могут быть довольно быстрыми. Ed James
5

Я проверил код, предоставленный Ником Крейвером, и обнаружил, что кеширование DOM работает быстреетолько если содержимое элемента не изменяется, Однако если вы изменяете строку в каждой итерации цикла for, скоростьрезко уменьшается.

Вот тот же модифицированный код (протестируйте его на Fiddle:http://jsfiddle.net/Ps5ja/42/)

console.time('concat');
var html = "";
for(var i = 0; i < 500; i++) {
    html += '<div><span>Some More Stuff</span></div>';
    html += '<div>Some Conditional Content</div>';
}
var elem = $(html);
console.timeEnd('concat');

console.time('DOM');
var parent = $("<div />")
for(var j = 0; j < 500; j++) {
    parent.append($('<div/>').append($('<span/>', {text :'Some More Stuff'})));
    parent.append($('<div/>',{ text: 'Some conditionalContent' }));
}
console.timeEnd('DOM');

console.time('concat caching');
var html = "";
for(var i = 0; i < 10000; i++)
    html += '<div><span>Some More Stuff</span></div><div>Some Conditional Content'+i+'</div>';
var elem = $(html);
console.timeEnd('concat caching');

console.time('concat array.join');
var arr = [];
for(i = 0; i < 10000; i++)
    arr.push('<div><span>Some More Stuff</span></div><div>Some Conditional Content'+i+'</div>');

var elem = $(arr.join(''));
console.timeEnd('concat array.join');

console.time('DOM caching - NO modification');
var parent = $("<div />")
// here the contained text is unchanged in each iteration
for(var j = 0; j <10000; j++)
    parent.append('<div><span>Some More Stuff</span></div><div>Some Conditional Content</div>');
console.timeEnd('DOM caching - NO modification');

console.time('DOM caching with modification');
var parent = $("<div />")
// here the contained text is modified in each iteration
// (the value od J is appended to the text)
for(var j = 0; j <10000; j++)
    parent.append('<div><span>Some More Stuff</span></div><div>Some Conditional Content'+j+'</div>');
console.timeEnd('DOM caching with modification');

Таким образом, кеширование DOM работает быстрее, только если вы планируете повторять один и тот же фрагмент HTML снова и снова. Если нет, переходите к конкатенации строк.

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

0

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

Если будет задействовано много условных выражений или циклов, то вы можете использовать Array.join () вместо конкатенации строк с +. При конкатенации строк браузер генерирует много промежуточных строк, которые могут быть очень медленными; Array.join () пропускает все эти промежуточные строки. Для этих случаев я бы сделал что-то вроде:

var html = ['<div><span>Some More Stuff</span></div>'];
for (var i = 0; i < 1000; i++) {
    html.push('<div>Some Loop Content</div>');
}
$('#parent').append(html.join(''));
Как я уже говорил ранее, FF и, насколько мне известно, Chrome и Opera делают этот метод автоматически для конкататов строк, а в FF + = на самом деле быстрее, чем метод массива. Ed James
Я думаю, IE не будет поддерживаться для вашего проекта? Jeffery To

Похожие вопросы