.append VS.html Производительность VS.innerHTML
Этот сайт запускает тест между 3 различными методами, и кажется, что .html
- самый быстрый, а затем .append
. сопровождаемый .innerHTML
. Может кто-нибудь объяснить мне причины этого?
Здесь сайт, который делает сравнение среди трех методов.
Я прочитал этот ТАК вопрос, который связан, но я не совсем понимаю данный ответ, и этот вопрос мало что .innerHtml
отношении .innerHtml
.
Я не понимаю следующую часть:
Временный элемент создан, давайте назовем его x. x innerHTML установлен на строку HTML, которую вы передали. Затем jQuery перенесет каждый из созданных узлов (то есть, x childNodes) во вновь созданный фрагмент документа, который затем будет кешироваться в следующий раз. Затем он вернет фрагмент childNodes как свежую коллекцию DOM. Обратите внимание, что на самом деле все гораздо сложнее, так как jQuery выполняет несколько кросс-браузерных проверок и различные другие оптимизации. Например, если вы передадите просто <div></div>
в jQuery(), jQuery будет использовать ярлык и просто сделает document.createElement('div').
Может кто-нибудь упростить это?
Ответы
Ответ 1
Этот показатель бесполезен. innerHTML
всегда быстрее, чем манипуляция с DOM.
jQuery кажется быстрее, потому что он сначала подготавливает строку со всем HTML, а остальные выполняет одну операцию на каждой итерации. Также обратите внимание, что jQuery.html() использует innerHTML
всякий раз, когда это возможно.
jQuery из эталона
var html = '';
for (var i = 0; i < len; i++) {
html += '<div>Test ' + i + '</div>';
}
$('#list').html(html);
innerHTML из эталона
var list = document.getElementById('list');
for (var i = 0; i < len; i++) {
list.innerHTML = list.innerHTML + '<div>Test ' + i + '</div>';
}
Тест для innerHTML
был бы намного быстрее, если бы он был написан как:
var list = document.getElementById('list');
var html = '';
for (var i = 0; i < len; i++) {
html += '<div>Test ' + i + '</div>';
}
list.innerHTML = html;
http://jsben.ch/#/yDvKH
Ответ 2
Все трое мне мешают. Модификация dom на каждой итерации медленная.
http://jsperf.com/jquery-append-vs-html-list-performance/24
Я только что добавил новый тест:
var html = [];
for (var i = 0; i < len; i++) {
html.push('<div>Test ' + i + '</div>');
}
document.getElementById('list').innerHTML = html.join('');
Это намного быстрее.:)
Мой метод в Firefox составляет 26 тыс. Ops/sec против 1000, 10 000 и 13
![enter image description here]()
Ответ 3
Как .html
быть быстрее, чем .innerHTML
, когда .html
использует .innerHTML
с большим количеством дополнительного кода? Здесь .html
реализация в jQuery (взята непосредственно из файла jQuery).
html: function( value ) {
return jQuery.access( this, function( value ) {
var elem = this[0] || {},
i = 0,
l = this.length;
if ( value === undefined ) {
return elem.nodeType === 1 ?
elem.innerHTML.replace( rinlinejQuery, "" ) :
undefined;
}
// See if we can take a shortcut and just use innerHTML
if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
!wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
value = value.replace( rxhtmlTag, "<$1></$2>" );
try {
for (; i < l; i++ ) {
// Remove element nodes and prevent memory leaks
elem = this[i] || {};
if ( elem.nodeType === 1 ) {
jQuery.cleanData( getAll( elem, false ) );
elem.innerHTML = value;
}
}
elem = 0;
// If using innerHTML throws an exception, use the fallback method
} catch(e) {}
}
if ( elem ) {
this.empty().append( value );
}
}, null, value, arguments.length );
}
Ответ 4
Я думаю, что innerHTML быстрее с advesstion @Brat.
И при создании цикла и строки добавления должно быть полезно сначала использовать переменную.
Это делает вашу работу более хорошей.
хороший код:
var html = '';
for (var i = 0; i < len; i++) {
html += '<div>Test ' + i + '</div>';
};
$('#list').append(html);
неэффективный код:
for (var i = 0; i < len; i++) {
var html = '<div>Test ' + i + '</div>';
$('#list').append(html);
}
например: http://jsben.ch/#/yDvKH
Ответ 5
У меня также была проблема с большим перерисованием таблицы (размером около 10x100). Чтобы перерисовать всю таблицу, требуется около 300 мс.
Причина не в jQuery.append(), а не в dom.innerHTML, но при добавлении каждого элемента каждый раз.
Самый быстрый способ - конкатенировать все элементы html-кода, а затем добавить его в DOM.
Вот так:
function redrawMyTable( myData )
{
var innerHTML = '';
for ( var i = 0; i < myData.length; i++ )
{
innerHTML += createRowFromData( myData[i] );
}
myTableTbody.innerHTML = innerHTML;
}
function createRowFromData( rowData )
{
var rowHTML = '';
for ( var i = 0; i < rowData.length; i++ )
{
rowHTML += createCellFromData( rowData[i] );
}
return rowHTML;
}
function createCellFromData( cellData )
{
//Do everything you need, and return HTMl code as a string
return cellHTML;
}
Теперь он занимает всего 20-30 мс (против 300 мс:))
Ответ 6
Как сказал Барт, innerHTML всегда быстрее, чем манипулирование DOM.
Я тестировал hyperHTML, поэтому я решил поделиться своими результатами. На самом деле я изначально не запускал свои тесты в CodePen, и есть интересная разница в том, что времена jQuery намного ближе к внутреннему, выполняемому в CodePen.
Chrome:
createFragment 312.80 ms
hyperHTML 253.10 ms
innerHTML 62.70 ms
$.append 183.40 ms
Chrome (extensions off):
createFragment 225.10 ms
hyperHTML 139.80 ms
innerHTML 47.80 ms
$.append 170.90 ms
Firefox:
createFragment 141 ms
hyperHTML 84 ms
innerHTML 25 ms
$.append 90 ms
Edge:
createFragment 422.50 ms
hyperHTML 184.60 ms
innerHTML 44.00 ms
$.append 1629.69 ms
IE11:
createFragment 1180.29 ms
hyperHTML 13315.59 ms //slow fallbacks, IE sucks
innerHTML 125.70 ms
$.append 2382.49 ms
Я думаю, что все довольно просто. JavaScript не так быстр, как браузер при разборе и создании элементов, потому что браузер - это машинно-скомпилированный код. Вы не можете сделать лучше, чем просто передать HTML и позволить браузеру выполнять работу без перерыва.
Возможно, что некоторые различия в производительности связаны с проверкой XSS, что может показаться разумным.
function runbench(){
var data = [];
for (var i = 0; i < 10001; i++) {
data.push("<span>" + i + "</span>");
}
var perf=[];
var t0 = performance.now();
var c = document.createDocumentFragment();
for (var i = 0; i < 10001; i++) {
var e = document.createElement("span");
e.innerHTML = data[i];
c.appendChild(e);
}
document.querySelector('#createFragment').appendChild(c);
document.querySelector('#createFragment').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var t0 = performance.now();
document.querySelector('#innerHTML').innerHTML = data.join('');
document.querySelector('#innerHTML').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var t0 = performance.now();
$('#jqhtml').html(data.join(''));
document.querySelector('#jqhtml').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var t0 = performance.now();
$('#jqappend').append(data.join(''));
document.querySelector('#jqappend').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var t0 = performance.now();
hyperHTML.bind(document.querySelector('#hyperHTML'))
'${data.map(function (item) {
return "<span>" + item + "</span>";
})}';
document.querySelector('#hyperHTML').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var stats = [];
stats.push("<table>")
stats.push("<tr><td>createFrag: </td><td>" + perf[0].toFixed(2) + "</td></tr>");
stats.push("<tr><td>innerHTML: </td><td>" + perf[1].toFixed(2) + "</td></tr>");
stats.push("<tr><td>$.html: </td><td>" + perf[2] .toFixed(2) + "</td></tr>");
stats.push("<tr><td>$.append: </td><td>" + perf[3] .toFixed(2) + "</td></tr>");
stats.push("<tr><td>hyperHTML: </td><td>" + perf[4].toFixed(2) + "</td></tr>");
stats.push("</table>");
$('#performance').html(stats.join(''));
document.querySelector('#performance').classList='done';
}
https://codepen.io/jwhooper/pen/GzKwMV