JavaScript: 要素(タグ)の追加に時間がかかる場合の対処

JavaScriptで要素を追加する処理が必要なプログラムを作成するとき、大きくわけて2つの方法があります。

  • 1: 親になる要素(タグ)の innerHTML にタグの文字列をセットする
    • 1-1: 1つずつ innerHTML に += でタグを追加していく
    • 1-2: 文字列変数に += でタグ文字列をためておいて、最後に innerHTML にセットする
  • 2: 親になる要素(タグ)の appendChild() を呼び出して、タグのDOMオブジェクトを追加する
    • 2-1: 1つずつ appendChild() でDOMオブジェクトを追加していく
    • 2-2: DocumentFragment と呼ばれる一時的な器に対してDOMオブジェクトを appendChild() しておいて、すべて追加し終わったら親になる要素に DocumentFragmentappendChild() する

jQueryを使用している場合でも、内部では最終的に上記のいずれかになります。 ( html() でのセットは 1、 append() は 2 です)

少量の要素を追加する場合は、基本的にどれを使っても問題になることはあまりありません。

大量の要素を追加する場合は、1-1 や 2-1 だと速度が遅くなっていくのがわかるようになってきます。 1つ要素を追加するたびに、ブラウザ側で調整(リフロー)や再描画が発生するためです。 そのため、1-1 や 2-1 を使っていたら、 1-2 や 2-2 を使うようにしてください。

また、IE11の場合は 2-2 も遅いため、できるだけ 1-2 を使用するとよいです。 (innerHTML を可能な限り避けたい場合は、 document.createRange().createContextualFragment(タグ文字列) として得られた DocumentFragment を 1回だけ appendChild() する方法も取れます )

動作の確認 (10,000個のタグの追加)

※ jQueryなどのライブラリを使わない、純粋なJavaScriptだけの簡単なコードにしています。

(1-1: 1つずつ innerHTML += で追加。実行するととても遅くなるので注意してください)

(1-2: 最後に innerHTML = で追加)

(2-1: 1つずつ appendChild() で追加。実行するととても遅くなるので注意してください)

(2-2: 最後に appendChild()DocumentFragment を追加)

IE11の場合

IE11だと、2-2 (DocumentFragmentに appendChild() ) も、遅いです。 appendChild() などのDOM操作自体が遅く、実行されるたびに他のブラウザに比べて遅くなっていきます。

2-2

2-2

( IE11の開発者ツールから 2-2 のパフォーマンスを確認した例。 createElement() appendChild() などがされるたびに時間がかかっている )

innerHTMLの場合は、2-1よりも少ない時間になっています。

1-2

( IE11の開発者ツールから 1-2 のパフォーマンスを確認した例 )