15

OK、私は現在のプロジェクトでいくつかのバニラ 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

4 に答える 4

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 操作: 149 ミリ秒

ただし、複雑なフラグメントをキャッシュできる場合は、それらの DOM 要素を繰り返し作成するのではなく、複製するだけでよいという利点があります。2 番目のテストでは DOM が勝ちます。HTML メソッドがその DOM 要素コレクションを5000 回作成するのに対し、2 番目のキャッシュされたメソッドはそれを 1 回しか作成せず 5000 回複製するためです。このテストでは: HTML Concat: 282msDOM Manipulation: 157ms .

これはあなたの質問への直接の回答ではないことは承知していますが、コメントに基づいて、パフォーマンスについて好奇心が強いようです。そのため、表示/テスト/再生できるものを提供するだけです.

于 2010-04-22T11:36:11.800 に答える
5

Nick Craver が提出したコードをテストしたところ、要素のコンテンツが変更されない場合にのみ、 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 メソッドを使用しても速度が向上することはありません。しかし、私はそれを徹底的にテストしていません (反復回数が多いと変化する可能性があります)。

于 2013-06-11T12:37:02.047 に答える
2

innerHTML メソッドよりも DOM 操作を優先します。まず、DOM 操作は、innerHTML でエスケープする必要がある文字を正しく処理します。別の場合、通常は高速で、場合によってははるかに高速です。

于 2010-04-22T11:38:26.383 に答える
0

一般に、生成する html が大量にある場合は、すべてを 1 つの文字列にまとめて、ブラウザーにすべての要素を一度に生成させます。

多数の条件またはループが含まれる場合は、+ による文字列連結の代わりに 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(''));
于 2010-04-23T02:02:50.237 に答える