次の方法で共有


DHTML を加速する 12 の Tips

Mark Davis
Microsoft Corporation

November 2000

要約 : この記事では、パフォーマンスに大きく影響するいくつかの DHTML の機能と、DHTML ページの機能性を向上させるためのヒントについて説明します。

内容

はじめに
DHTML の変更をバッチ処理する
InnerText を使用する
DOM を使用して個々の要素を追加する
SELECT 要素のオプションを拡張する
DOM を使用してテーブルを更新する
一度作成したコードを何度も使用する
Dynamic Properties を多用しない
データ バインドを使用する
文書に対して Expando プロパティを使用しない
クラスとスタイル ルールの切り替えを避ける
親を検索する前にテキスト範囲を縮小する
その他

はじめに

Microsoft(R) Internet Explorer 4.0 に Dynamic HTML (DHTML) が導入されたことにより、Web ページの作成者や開発者は新しいプログラミング モデルを使用できるようになりました。それ以降、Web ページ作成者はこの高性能な機能を利用して、動的なコンテンツ、スタイル、および配置を可能にし、Web ユーザーに豊富な対話型操作を提供してきました。DHTML は柔軟であるため、多くの場合に目的とする内容を複数の方法で実現することができます。Internet Explorer の HTML 解析およびレンダリング コンポーネントで要求がどのように処理されるかを理解することは、ジョブに最適な方法を決定する際のヒントになります。この記事では、パフォーマンスに大きく影響するいくつかの DHTML の機能と、ページの機能性を向上させるためのヒントについて説明します。

DHTML の変更をバッチ処理する

DHTML Web ページのパフォーマンスを向上させる際に最も重要な点は、ページの HTML コンテンツに対する変更の適用方法をどのように向上させるかです。Web ページに多くの更新方法があることを理解することは、重要です。Web ページ作成者は、クライアント スクリプトから HTML テキストのブロックを適用したり、DHTML object modelW3C document object model (DOM) を使用して個々の HTML 要素にアクセスすることができます。HTML コンテンツに変更があるたびに、Internet Explorer の HTML 解析およびレンダリング コンポーネントは、ページの内部表現を認識し、文書のレイアウトとフローを再計算し、変更内容を表示する必要があります。実際のパフォーマンスは変更内容と Web ページのコンテンツによって異なりますが、これらの操作には比較的コストがかかります。個々の要素にアクセスするのではなく、HTML のテキスト ブロックを適用する場合は、HTML パーサーを起動する必要があるため、さらにパフォーマンス コストがかかります。HTML テキストを受け付けるメソッドとプロパティには、insertAdjacentHTML メソッド、pasteHTML メソッド、innerHTML プロパティ、および outerHTML プロパティがあります。

Tip 1: HTML コンテンツには、1 つのスクリプト関数で変更を加えます。マウスの移動に対する反応のように、複数のイベント ハンドラを使用する設計では、変更を 1 か所にまとめます。

HTML 解析およびレンダリング コンポーネントに関するもう 1 つの重要な事実は、スクリプトから制御が戻るとすぐに Web ページのレイアウトを再計算して表示する点です (たとえば、スクリプトのイベント ハンドラ関数が終了した場合や、setTimeout などのメソッドが呼び出された場合)。それでは、Internet Explorer による変更処理の方法について多少理解したところで、Web ページのパフォーマンスを向上させてみましょう。

Tip 2: 文書には、複数回の更新を加えるのではなく、1 つの HTML 文字列を作成して一度に変更を加えます。HTML コンテンツが必要でない場合は、innerText プロパティの使用を検討します。

次の例では、遅いメソッドで、innerHTML プロパティが設定されるたびに HTML パーサーを呼び出しています。パフォーマンスを向上させるために、1 つの文字列を作成してから、それを innerHTML プロパティに割り当てる方法が考えられます。

サンプルの表示

遅い :

 divUpdate.innerHTML = "";
 for ( var i=0; i<100; i++ )
 {
  divUpdate.innerHTML += "<SPAN>これはより遅いメソッドです。</SPAN>";
 }

速い :

 var str="";
 for ( var i=0; i<100; i++ )
 {
  str += "<SPAN>これは、文字列を使用しているため、より速いメソッドです。</SPAN>";
 }
 divUpdate.innerHTML = str;

詳細については、Dynamic Content(英語) を参照してください。

InnerText を使用する

DHTML オブジェクト モデルでは、HTML 要素のテキスト コンテンツは innerText プロパティによってアクセスされます。これに対して、W3C DOM では、個別の子テキスト ノードが提供されます。DOM の createTextNode メソッドを呼び出すよりも、DHTML の innerText プロパティを使用 して要素のコンテンツを直接更新する方が高速です。

Tip 3: テキスト コンテンツの更新には、innerText プロパティを使用します。

次の例は、innerText プロパティを使用してパフォーマンスを向上させる方法を示しています。

サンプルの表示

遅い :

 var node;
 for (var i=0; i<100; i++)
 {
  node = document.createElement( "SPAN" );
  node.appendChild(  document.createTextNode( " createTextNode() を使用" ) );
  divUpdate.appendChild( node );
 }

速い :

 var node;
 for (var i=0; i<100; i++)
 {
  node = document.createElement( "SPAN" );
  node.innerText = " innerText プロパティを使用 ";
  divUpdate.appendChild( node );
 }

DOM を使用して個々の要素を追加する

前に説明したとおり、HTML テキストを適用するメソッドにアクセスすると、HTML パーサーが呼び出され、パフォーマンスが損なわれます。このような理由から、要素を追加する場合は、insertAdjacentHTML メソッドを 1 回呼び出すよりも、createElement メソッドと insertAdjacentElement メソッドを使用した方が高速です。

Tip 4: 多くの場合、insertAdjacentHTML メソッドを呼び出すよりも、createElement メソッドと insertAdjacentElement メソッドを呼び出す方が高速です。

DHTML の更新をバッチ処理して、insertAdjacentHTML メソッドを 1 回呼び出しても、パフォーマンスは向上しますが、場合によっては DOM で直接要素を作成した方が効率的です。両方の方法を試し、より速い方に決定するとよいでしょう。

サンプルの表示

遅い :

 for (var i=0; i<100; i++)
 {
  divUpdate.insertAdjacentHTML( "beforeEnd", "<SPAN> insertAdjacentHTML() を使用</SPAN>" );
 }

速い :

 var node;
 for (var i=0; i<100; i++)
 {
  node = document.createElement( "SPAN" );
  node.innerText = " insertAdjacentElement() を使用";
  divUpdate.insertAdjacentElement( "beforeEnd", node );
 }

SELECT 要素のオプションを拡張する

SELECT要素に多数の OPTION 要素を追加する場合は、前に説明した HTML テキスト メソッドの使用に関する法則の例外になります。この場合、オプションのコレクションに対するアクセスには、createElement メソッドを呼び出すよりも innerHTML プロパティを使用する方が効率的です。

Tip 5: SELECT 要素に多数のオプションを追加する場合は、innerHTML を使用します。

文字列の連結を使用して SELECT 要素の HTML テキストを作成し、次にこのヒントを使用して innerHTML プロパティを設定します。オプションの数が非常に多い場合には、文字列の連結もパフォーマンスに影響する場合があります。そのような状況では、配列を作成して、Microsoft JScriptR の join メソッドを呼び出して、最後に OPTION 要素の HTML テキストの連結を実行します。

サンプルの表示

遅い :

 var opt;
 divUpdate.innerHTML = "<SELECT ID='selUpdate'></SELECT>";
 for (var i=0; i<1000; i++)
 {
  opt = document.createElement( "OPTION" );
  selUpdate.options.add( opt );
  opt.innerText = "項目 " + i;
 }

速い :

 var str="<SELECT ID='selUpdate'>";
 for (var i=0; i<1000; i++)
 {
  str += "<OPTION>項目 " + i + "</OPTION>";
 }
 str += "</SELECT>";
 divUpdate.innerHTML = str;

さらに速い :

 var arr = new Array(1000);
 for (var i=0; i<1000; i++)
 {
  arr[i] = "<OPTION>項目 " + i + "</OPTION>";
 }
 divUpdate.innerHTML = "<SELECT ID='selUpdate'>" + arr.join() + "</SELECT>";

DOM を使用してテーブルを更新する

テーブルに行とセルを挿入する場合は、DHTML テーブル オブジェクト モデルの一部である insertRow メソッドと insertCell メソッドを使用するよりも、DOM メソッドを使用した方が効率的です。大きなテーブルを作成する場合には、特に効率が良くなります。

Tip 6: 大きなテーブルを作成する場合は、DOM メソッドを使用します。

サンプルの表示

遅い :

 var row;
 var cell;
 for (var i=0; i<100; i++)
 {
  row = tblUpdate.insertRow();
  for (var j=0; j<10; j++)
  {
    cell = row.insertCell();
    cell.innerText = "行 " + i + ", セル " + j;
  }
 }

速い :

 var row;
 var cell;
 var tbody = tblUpdate.childNodes[0];
 tblUpdate.appendChild( tbody );
 for (var i=0; i<100; i++)
 {
  row = document.createElement( "TR" );
  tbody.appendChild( row );
  for (var j=0; j<10; j++)
  {
    cell = document.createElement( "TD" );
    row.appendChild( cell );
    cell.innerText = "行 " + i + ", セル " + j;
  }
 }

一度作成したコードを何度も使用する

Web サイトの共通操作にスクリプトを使用している場合は、そのような関数を個別のファイルに記述し、複数の Web ページで再利用できるように考慮してください。コードの保守性を高め、スクリプト ファイルを常にブラウザ キャッシュ内に置いて、ユーザーのサイト訪問中に一度だけユーザーのマシンにダウンロードするようにします。同様に、共通のスタイル ルールを個別のファイルに分けることによってもパフォーマンスは向上します。

Tip 7: 共通のコードを 1 つの Behavior や個別のファイルに配置することにより、スクリプトを再利用します。

スクリプト関数をよりうまく再利用するには、共通のスクリプト操作を DHTML に関連付けられた、または要素 Behaviors に記述します。Behavior は、スクリプトを再利用し、HTML からアクセス可能なコンポーネントを構築するための優れた手段であり、ユーザーのオブジェクト、メソッド、プロパティ、およびイベントを使用した DHTML オブジェクト モデルの拡張を可能にします。viewlink 機能を使用しないBehavior の場合、さらに効率的なコードのカプセル化を行うために、Internet Explorer 5.5 で使用可能な lightweight Behavior の機能を使用することを検討してください。また、スクリプト コードが単一の SCRIPT ブロックに記述されている場合は、さらにパフォーマンスが高くなります。

Dynamic Properties を多用しない

Dynamic Properties を使用すると、プロパティ値に式を使用できます。この式は実行時に評価され、結果の値がプロパティに適用されます。これは、強力な機能です。Dynamic Properties は、ページのスクリプト量を削減するために使用できます。しかし、式は定期的に再計算する必要があり、多くの場合ほかのプロパティ値に依存しているため、パフォーマンスにとって逆効果になる場合もあります。プロパティの配置の場合には、特にこの傾向が顕著になります。

Tip 8: Dynamic Properties の使用を制限します。

データ バインドを使用する

データ バインドは、データベース クエリの結果や XML Data Island のコンテンツを Web ページの要素にバインドできるようにする強力な機能です。データ バインドを使用すると、データのソートやフィルタ処理の機能を提供できるほか、サーバーに戻ってデータをフェッチすることなくデータの異なるビューを得ることができます。企業データを折れ線グラフ、棒グラフ、および円グラフで表示し、そのデータをオフィス、製品、または販売期間でソートするボタンを備えた Web ページがあるとします。このようなすべての機能が、サーバーを一度訪問しただけで作成できます。

Tip 9: データ バインドを使用して、内容豊かなクライアント側のデータ表示を提供します。

データ バインドの詳細については、次の記事を参照してください。

  • Data Binding(英語)
  • ページのデータをバインドする
  • 単純で軽量な仮想データバインド

文書に対して Expando プロパティを使用しない

expando プロパティは、あらゆるオブジェクトに追加可能な任意のプロパティです。これは、現在の Web ページに情報を保存する場合に便利なプロパティであり、DHTML オブジェクト モデルを拡張するもう 1 つの方法になります。たとえば、HTML 要素に "clicked" プロパティを割り当て、それを使用してクリックされた要素をユーザーに示すことができます。また、expando プロパティは、イベントを起動してイベント ハンドラ関数に追加のコンテキスト情報を提供する場合にも使用できます。expando プロパティは、どのような使用目的であっても document オブジェクトには使用しないでください。使用すると、プロパティにアクセスしたときにその文書で余分な再計算の実行が必要になります。

Tip 10: window オブジェクトについては expando プロパティを設定します。

サンプルの表示

遅い :

for (var i=0; i<1000; i++)
 {
  var tmp;
  window.document.myProperty = "項目 "+i;
  tmp = window.document.myProperty;
 }

速い :

for (var i=0; i<1000; i++)
 {
  var tmp;
  window.myProperty = "項目 "+i;
  tmp = window.myProperty;
 }

クラスとスタイル ルールの切り替えを避ける

クラス およびスタイル ルールの切り替えでは、文書全体の再計算とレイアウトが必要となるため、操作コストが高くなる場合があります。Web サイトでスタイル シートを使用してコンテンツの代替ビューを提供する場合は、要素の className プロパティやクラスに関連付けられた styleSheet オブジェクトを修正するのではなく、変更する要素の style オブジェクトを直接修正することを検討してください。

Tip 11: コンテンツのプレゼンテーションを変更する場合は、style オブジェクトを直接修正します。

親を検索する前にテキスト範囲を縮小する

TextRange オブジェクトは、ユーザーが選択したテキストや、BODY などの HTML 要素から検索されたテキストの領域を表します。テキスト範囲の親は、parentElement メソッドを呼び出すことによって識別できます。複雑なテキスト範囲の場合は、collapse メソッドを呼び出してから parentElement メソッドを呼び出すとより効率的です。

Tip 12: parentElement メソッドには、テキスト範囲を縮小してからアクセスします。

詳細については、「Using TextRange Object」(英語) を参照してください。

その他

パフォーマンス向上のそのほかのヒントについては、次の記事を参照してください。

Mark Davis は、Internet Explorer SDK ドキュメント チームのソフトウェア開発技術者です。最新の Internet Explorer テクノロジの探索に携わっていないときには、彼はおそらく地元米国北西部の山岳地帯を探索しています。