jQuery .append VS .html VS .innerHTML 性能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18393981/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 21:31:32  来源:igfitidea点击:

.append VS .html VS .innerHTML performance

javascriptjquery

提问by Computernerd

This site's run a test between the 3 different methods and it seems .htmlis the fastest, followed by .append. followed by .innerHTML. Can someone explain to me the reasons why?

该站点在 3 种不同方法之间进行了测试,它似乎.html是最快的,其次是.append. 其次是.innerHTML。有人可以向我解释原因吗?

Here's the site which does the comparisonamong the three methods.

这是对三种方法进行比较网站

I have read this this SO questionwhich is related but I don't really understand the given answer, and the question didn't really elaborate much regarding .innerHtml.

我已经阅读了这个相关的SO 问题,但我并不真正理解给定的答案,并且该问题并没有对.innerHtml.

I don't understand the following part:

我不明白以下部分:

A temporary element is created, let's call it x. x's innerHTML is set to the string of HTML that you've passed. Then jQuery will transfer each of the produced nodes (that is, x's childNodes) over to a newly created document fragment, which it will then cache for next time. It will then return the fragment's childNodes as a fresh DOM collection. Note that it's actually a lot more complicated than that, as jQuery does a bunch of cross-browser checks and various other optimisations. E.g. if you pass just <div></div>to jQuery(), jQuery will take a shortcut and simply do document.createElement('div').

创建了一个临时元素,我们称之为 x。x 的innerHTML 设置为您传递的HTML 字符串。然后 jQuery 将每个生成的节点(即 x 的 childNodes)转移到一个新创建的文档片段,然后它会在下一次缓存。然后它将片段的 childNodes 作为一个新的 DOM 集合返回。请注意,它实际上比这复杂得多,因为 jQuery 进行了大量跨浏览器检查和各种其他优化。例如,如果您只传递<div></div>给 jQuery(),jQuery 将采用快捷方式并简单地执行 document.createElement('div')。

Can someone simplify this?

有人可以简化这个吗?

回答by Bart

That benchmark is worthless. innerHTMLis always faster than DOM manipulation.

那个基准毫无价值。innerHTML总是比 DOM 操作快。

jQuery seemsfaster because it prepares a string with all the HTML first while the others do one operation each iteration. Also note that jQuery.html() uses innerHTMLwhenever it can.

jQuery看起来更快,因为它首先准备一个包含所有 HTML 的字符串,而其他人每次迭代都执行一个操作。还要注意 jQuery.html() 会innerHTML尽可能使用。

jQuery from benchmark

来自基准测试的jQuery

var html = '';
for (var i = 0; i < len; i++) {
  html += '<div>Test ' + i + '</div>';
}

$('#list').html(html);

innerHTML from benchmark

来自基准测试的innerHTML

var list = document.getElementById('list');
for (var i = 0; i < len; i++) {
  list.innerHTML = list.innerHTML + '<div>Test ' + i + '</div>';
}


The test for innerHTMLwould be a lot faster if it was written like:

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

http://jsben.ch/#/yDvKH

回答by Phill

All three are slow to me. Modifying the dom on each iteration is slow.

这三个对我来说都很慢。在每次迭代中修改 dom 很慢。

http://jsperf.com/jquery-append-vs-html-list-performance/24

http://jsperf.com/jquery-append-vs-html-list-performance/24

I just added a new test in there:

我刚刚在那里添加了一个新测试:

var html = [];
for (var i = 0; i < len; i++) {
  html.push('<div>Test ' + i + '</div>');
}

document.getElementById('list').innerHTML = html.join('');

This is much faster again. :)

这又要快得多了。:)

My method in Firefox does 26k Ops/sec vs 1,000, 10,000, and 13

我在 Firefox 中的方法是 26k Ops/sec vs 1,000、10,000 和 13

enter image description here

在此处输入图片说明

回答by invisal

How can .htmlbe faster than .innerHTMLwhen the .htmlis using .innerHTMLwith a lot of extra code? Here .htmlimplementation in jQuery (taken directly from jQuery file).

如何.html比使用大量额外代码.innerHTML时更快?这里在 jQuery 中实现(直接取自 jQuery 文件)。.html.innerHTML.html

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, "<></>" );

            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 );
}

回答by akbarbin

I think the innerHTML is faster with suggesstion @Brat.

我认为使用建议@Brat 的innerHTML 更快。

And on creating loop and appending string should be good on using variable first. It is make your performance more good.

在创建循环和附加字符串时,最好先使用变量。它是让你的表现更好。

good code:

好的代码:

var html = '';
for (var i = 0; i < len; i++) {
  html += '<div>Test ' + i + '</div>';
};
$('#list').append(html);

not efficient code:

效率不高的代码:

for (var i = 0; i < len; i++) {
  var html = '<div>Test ' + i + '</div>';
  $('#list').append(html);
}

for example: http://jsben.ch/#/yDvKH

例如:http: //jsben.ch/#/yDvKH

回答by jwhooper

As Bart said, innerHTML is always faster than DOM manipulation.

正如 Bart 所说,innerHTML 总是比 DOM 操作快

I was testing hyperHTML, so I thought I share my results. I didn't actually run my benchmarks in CodePen originally, and there is an interesting difference in that the jQuery times are much closer to innerHTML running in CodePen.

我正在测试 hyperHTML,所以我想我要分享我的结果。实际上,我最初并没有在 CodePen 中运行我的基准测试,并且有一个有趣的区别,即 jQuery 时间更接近于在 CodePen 中运行的 innerHTML。

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

I think it is all pretty simple. JavaScript is not as fast as the browser at parsing and creating elements, because the browser is machine specific compiled code. You can't do better than just handing over the HTML and letting the browser do the work without interruption.

我认为这一切都很简单。JavaScript 在解析和创建元素方面不如浏览器快,因为浏览器是机器特定的编译代码。没有比仅仅移交 HTML 并让浏览器不间断地完成工作做得更好的了。

It is possible that some of the performance differences are due to XSS checking, which would seem prudent.

某些性能差异可能是由于 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

https://codepen.io/jwhooper/pen/GzKwMV

回答by Олег Всильдеревьев

I also had a problem with big table redraw (about 10x100 size). It takes about 300ms to redraw whole table.

我也遇到了大表重绘(大约 10x100 大小)的问题。重绘整个表大约需要300ms。

The reason was not in the jQuery.append() and not in dom.innerHTML, but in appending each element each time.

原因不是在 jQuery.append() 中,也不是在 dom.innerHTML 中,而是在每次附加每个元素中。

The fastest way is to concatenate all elements html code and then append it to DOM. Like this:

最快的方法是连接所有元素的 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;
}

Now it takes only 20-30 ms (against 300ms :))

现在只需要 20-30 毫秒(针对 300 毫秒 :))

回答by Rolf

6 years later

6年后

Point is - don't manipulate the live DOM. Do it outside. Today, it doesn't matter where. You can use a HTML String, a DocumentFragment (which excludes Internet Explorer) or create a new Element but don't add it to the DOM, fill it as you need and THEN add it.

重点是 - 不要操作实时 DOM。在外面做。今天,无论在哪里。您可以使用 HTML 字符串、DocumentFragment(不包括 Internet Explorer)或创建一个新元素,但不要将其添加到 DOM,根据需要填充它,然后添加它。

On Chrome and Firefox my observation is that it's all the same run time, give or take a few percent.

在 Chrome 和 Firefox 上,我的观察是它们的运行时间都是相同的,给予或接受几个百分比。

Building a long HTML String in chunks that are stored in an array and then join('')-ed is also not necessary any more. Years ago, I measured big time differences. Not today. Point one: there's no recognizable time difference (on Chrome and FF), and point two: the time isn't lost at this point, but in rendering.

在存储在数组中的块中构建一个长的 HTML 字符串,然后 join('')-ed 也不再需要了。多年前,我测量了很大的时差。今天不行。第一点:没有可识别的时间差异(在 Chrome 和 FF 上),第二点:此时没有丢失时间,而是在渲染中丢失了时间。