今回は jQuery コードパフォーマンスの最適化方法の概要、jQuery コードのパフォーマンスの最適化の注意事項について説明します。以下は実際的なケースです。見てみましょう。
1. 要素の検索には常に #id を使用します。
jQuery で最も高速なセレクターは、JavaScript の getElementById( ) メソッドに直接マップされるためです。
単一の要素を選択する
<p id="content"> <form method="post" action="/"> <h2>Traffic Light</h2> <ul id="traffic_light"> <li><input type="radio" class="on" name="light" value="red" /> Red</li> <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li> <li><input type="radio" class="off" name="light" value="green" /> Green</li> </ul> <input class="button" id="traffic_button" type="submit" value="Go" /> </form> </p>
パフォーマンスの悪いボタンを選択する方法:
var traffic_button = $('#content .button');
代わりにボタンを直接選択する:
var traffic_button = $('#traffic_button');
複数の要素を選択する
複数の要素を選択することについて話していますが、実際に必要なものは何ですかDOM トラバーサルとループがパフォーマンス低下の原因であることはわかっています。パフォーマンスの損失を最小限に抑えるために、常に最も近い親 ID を使用して検索してください。
var traffic_lights = $('#traffic_light input');
2. クラスの前でタグを使用する
jQuery で 2 番目に速いセレクターは、タグ セレクター ($('head')) であり、これは JavaScript の getElementsByTagName( ) メソッドに直接マップされるためです。
<p id="content"> <form method="post" action="/"> <h2>Traffic Light</h2> <ul id="traffic_light"> <li><input type="radio" class="on" name="light" value="red" /> Red</li> <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li> <li><input type="radio" class="off" name="light" value="green" /> Green</li> </ul> <input class="button" id="traffic_button" type="submit" value="Go" /> </form> </p>
常にクラスの前にタグ名を追加してください (ID から渡すことを忘れないでください)
var active_light = $('#traffic_light input.on');
注: クラス セレクターは、IE の jQuery で最も遅いセレクターであり、DOM 全体をループします。可能であれば使用を避けるようにしてください。 ID の前にタグを追加しないでください。 たとえば、ID が content である
を見つけるためにすべての
要素をループするため、非常に遅くなります。
var content = $('p#content');
同様に、複数の ID からの継承も冗長です。
var traffic_light = $('#content #traffic_light');
3. jQuery オブジェクトをキャッシュする
jQuery オブジェクトを変数に保存する習慣をつけましょう (上記の例のように)。たとえば、これは行わないでください:
$('#traffic_light input.on).bind('click', function(){...}); $('#traffic_light input.on).css('border', '3px dashed yellow'); $('#traffic_light input.on).css('background-color', 'orange'); $('#traffic_light input.on).fadeIn('slow');
代わりに、作業を続行する前に jQuery 変数をローカル変数に保存します。
var $active_light = $('#traffic_light input.on'); $active_light.bind('click', function(){...}); $active_light.css('border', '3px dashed yellow'); $active_light.css('background-color', 'orange'); $active_light.fadeIn('slow');
ヒント: $ 接頭辞を使用して、ローカル変数が jQuery パッケージ セットであることを示します。アプリケーション内で jQuery の選択操作を複数回繰り返さないように注意してください。 ボーナス ヒント: jQuery オブジェクトの結果の遅延ストレージ。
プログラム内の別の場所で jQuery 結果オブジェクトを使用する場合、または関数が複数回実行される場合は、グローバル スコープのオブジェクトにキャッシュします。 jQuery 結果オブジェクトを保持するグローバル コンテナを定義することで、他の関数でそれを参照できるようになります。
// Define an object in the global scope (i.e. the window object) window.$my ={ // Initialize all the queries you want to use more than once head : $('head'), traffic_light : $('#traffic_light'), traffic_button : $('#traffic_button')}; function do_something(){ // Now you can reference the stored results and manipulate them var script = document.createElement('script'); $my.head.append(script); // When working inside functions, continue to save jQuery results // to your global container. $my.cool_results = $('#some_ul li'); $my.other_results = $('#some_table td'); // Use the global functions as you would a normal jQuery result $my.other_results.css('border-color', 'red'); $my.traffic_light.css('border-color', 'green'); }
4. チェーンのより良い利用
前の例は次のように書くこともできます:
var $active_light = $('#traffic_light input.on'); $active_light.bind('click', function(){...}) .css('border', '3px dashed yellow') .css('background-color', 'orange') .fadeIn('slow');
これにより、記述するコードが減り、JavaScript がより軽量になります。
5. サブクエリを使用する
jQuery を使用すると、パッケージ セットに他のセレクターをアタッチできます。親オブジェクトをローカル変数に保存したため、将来的にはセレクターのパフォーマンスのオーバーヘッドが軽減されます。
<p id="content"> <form method="post" action="/"> <h2>Traffic Light</h2> <ul id="traffic_light"> <li><input type="radio" class="on" name="light" value="red" /> Red</li> <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li> <li><input type="radio" class="off" name="light" value="green" /> Green</li> </ul> <input class="button" id="traffic_button" type="submit" value="Go" /> </form> </p>
たとえば、サブクエリを使用して、後の操作のためにアクティブなライトと非アクティブなライトをキャッシュできます。
var $traffic_light = $('#traffic_light'), $active_light = $traffic_light.find('input.on'), $inactive_lights = $traffic_light.find('input.off');
ヒント: 複数のローカル変数をカンマで区切って一度に定義すると、バイト数を節約できます。
6. 直接の DOM 操作を制限する
DOM 操作の基本的な方法は、メモリ内に DOM 構造を作成し、その後 DOM 構造を更新することです。これは jQuery にとって最良のアプローチではありませんが、JavaScript にとっては効率的です。 DOM 構造を直接操作すると、パフォーマンスが低下します。 たとえば、要素のリストを動的に作成する必要がある場合は、これを実行しないでください:
var top_100_list = [...], // assume this has 100 unique strings $mylist = $('#mylist'); // jQuery selects our <ul> element for (var i=0, l=top_100_list.length; i<l; i++){ $mylist.append('<li>' + top_100_list[i] + '</li>'); }
代わりに、DOM 構造に要素を挿入する前に文字列内の要素のセットを作成したいと考えています。
コード
var top_100_list = [...], // assume this has 100 unique strings $mylist = $('#mylist'), // jQuery selects our <ul> element top_100_li = ""; // This will store our list items for (var i=0, l=top_100_list.length; i<l; i++){ top_100_li += '<li>' + top_100_list[i] + '</li>'; } $mylist.html(top_100_li);
より早い方法では、DOM 構造に挿入する前に、常に親ノードに多くの要素を含める必要があります
var top_100_list = [...], // assume this has 100 unique strings $mylist = $('#mylist'), // jQuery selects our <ul> element top_100_ul = '<ul id="#mylist">'; // This will store our entire unordered list for (var i=0, l=top_100_list.length; i<l; i++){ top_100_ul += '<li>' + top_100_list[i] + '</li>'; } top_100_ul += '</ul>'; // Close our unordered list $mylist.replaceWith(top_100_ul);
上記に従ってもパフォーマンスについてまだ少し混乱している場合は、以下を参照できます。
* jQuery が提供する Clone() メソッドを試してください。 Clone() メソッドはノード番号のコピーを作成し、このコピーに対して操作を実行できます。
* DOM DocumentFragments を使用します。jQuery の作成者が指摘しているように、最初に必要な構造を作成してから (上記の文字列の場合と同様に)、jQuery の挿入メソッドまたは置換メソッドを使用します。 .
7、事件委托(又名:冒泡事件)
除非特别说明,每一个JavaScript事件(如click, mouseover 等)在DOM结构树上都会冒泡到它的父元素上。如果我们想让很多elements(nodes)调用同一个function这是非常有用的。取而代之的是 你可以只对它们的父级绑定一次,而且可以计算出是哪一个节点触发了事件,而不是绑定一个事件监听器到很多节点上这种效率低下的方式。例如,假如我们要开发 一个包含很多input的大型form,当input被选择的时候我们想绑定一个class name。像这样的帮定是效率低下的:
$('#myList li).bind('click', function(){ $(this).addClass('clicked'); // do stuff });
反而,我们应该在父级侦听click事件。
$('#myList).bind('click', function(e){ var target = e.target, // e.target grabs the node that triggered the event. $target = $(target); // wraps the node in a jQuery object if (target.nodeName === 'LI') { $target.addClass('clicked'); // do stuff } });
父节点担当着发报机的工作,可以在触发了事件的目标element上做一些工作。如果你发现自己把一个event listener帮定到很多个element上,那么你这种做法是不正确的。
8、消除查询浪费
虽然jQuery对没有找到任何匹配的elements处理的很好,但是它还是需要花费时间去查找的。如果你的站点有一个全局的JavaScript,你可能会把每个jQuery function都放在 $(document).ready(function(){ // all my glorious code })里。 不要这样做。只去放一些页面上适合用到的function。这样做最有效的方式是你的模板可以完全控制任何时候或者地方执行JavaScript以内联脚 本的方式初始化function。例如,在你的“article”页面模板里,你可能在body标签关闭之前包含以下代码