web-dev-qa-db-ja.com

AngularJSアプリケーションを高速化する方法は?

ページグリッド(2つのネストされたng-repeat)を備えたAngularJSアプリがあります。 1ページには約25x40の入力要素があります。 1000バインディングを作成した当初は、ページングパフォーマンスは許容範囲でした。

しかし、ページの複雑さが増します:​​動的クラス、さまざまなコンテキストメニュー、グリッドの各セルの条件付きコンテンツ。また、推定6000バインディング(入力要素ごとに6)で、ページングが遅くなり、使用できなくなりました。

私の質問は、AngularJSのパフォーマンスの問題に一般的にどのように対処するかです。明らかに最初のステップは測定することです。しかし、Chromeプロファイラーの結果は、続行方法を知ることからほど遠く、私にそれほど多くを教えません。

 Self      Total                           Function
-----------------------------------------------------------------
24 ms    2.79 s    angular.js:7997         Scope.$digest
 1 ms       1 ms   controllers.js:365      setViewportData
16 ms     692 ms   angular.js:13968        ngRepeatWatch
 8 ms      22 ms   angular.js:6439         extend.literal
 9 ms    1.22 s    angular.js:14268        ngSwitchWatchAction
16 ms      45 ms   angular.js:12436        ngModelWatch
 0        621 ms   angular-ui-4.0.js:264   initDateWidget
 0         13 ms   angular.js:12859        ngClassWatchAction
 0         70 ms   angular.js:14184        ngStyleWatchAction
 1 ms       5 ms   angular-ui-4.0.js:261   getOptions
 0         16 ms   angular.js:579          copy
 0          1 ms   angular.js:4558         interpolateFnWatchAction
 1 ms       2 ms   angular.js:5981         token.fn.extend.assign
 0         37 ms   angular.js:8151         Scope.$eval
 1 ms       1 ms   angular.js:6137         extend.constant
14 ms      16 ms   angular.js:651          equals
 1 ms       1 ms   angular.js:4939         $interpolate.fn

余談ですが、「Object.observe()」が将来的に高速化する可能性はありますか(「initDateWidget」を無視すると、明らかに別のトピックになります)?

27
woelling

Angularアプリを最も高速化するためにできることは、できる限りバインディングを減らすことです。これを行う1つの方法は、テーブルを作成するディレクティブを作成することですng-repeatsを使用する代わりにDOM操作を使用して、これにより、処理する必要のある全体的なウォッチの数が減少し、$ digestが大幅に高速化されます。

これを行うのは醜いことはわかっていますが、Angularは実際には3000以上のバインディングをセットアップすることを意図していません。ダイジェストを実行し、オブザーバーパターンではないため、多くの設定を行うと、処理速度が実際に低下します。

Ng-repeatを引き続き使用するハイブリッドアプローチを実行することもできますが、すべての値はカスタムディレクティブからの直接DOM操作でDOMに配置されるため、すべてのバインディングが回避されます。

28
Ben Lesh

まだ行っていない場合は、AngularJS Chromeプラグイン、Batarangをインストールしてください。これにより、どのバインディングが問題の原因となっているかを特定するのに役立ちます。 https://chrome.google .com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl = ja

他の答えが示唆しているように、探しているのは、バインドするモデルが画面に表示しているサブセットである、テーブルの無限スクロール設定の小さなケースです。

Ng-gridコンポーネントはこれを実装しており、直接使用するか、手法を盗むかを検討する価値があります。 http://angular-ui.github.com/ng-grid/

21
Brad Green

資源

大きなリストでのangularJSのパフォーマンスに関するこの投稿 には、パフォーマンスのチューニングに使用できるオプションの概要があります。

上記の回答(Batarangプラグインを除く)も記載されています。これは、その記事のヒントの概要にすぎません。

LimitTo(改ページ)でデータを削減する

より明白な解決策の1つは、ビュー内のアイテムの数を減らすことによってバインディングの量を減らすことです。データのページ分割は、ng-repeatlimitToフィルターを使用して行うことができます。

巨大なデータセット(angular.js)でngRepeatのパフォーマンスを向上させる方法? この記事にも jsbinの例 がリンクされています。

また、すべての$ digestで評価されるため、データ提供にインラインメソッドを使用しないようにしてください。

<li ng-repeat="item in filteredItems()"> // Bad idea, since very often evaluated.
<li ng-repeat="item in items"> // Way to go! 

Bindonceでバインディングを削除する

別の明白な解決策は、特定の要素のバインディングを削除することです。確かにこれは、更新がビューに反映されなくなることを意味します。

bindonceソリューションは、双方向のバインディングを削除するだけではありません。基本的に、バインディングが削除される前に、値がバインドされるのを待ちます。よく読んでください。詳細は bindonceプロジェクト を確認してください。

上にリストされている記事には、2つのリストを処理するパターンに関する情報もあります。 1つは視覚化用、もう1つはデータソース用です。

Ng-gridを使用する

Ng-gridには、現在表示されている要素のみをレンダリングするという利点があります。詳しくは http://angular-ui.github.io/ng-grid/ をご覧ください。

同様のng-ifは、DOMツリーから非表示の要素を完全に削除しますが、ng-showは、それらをそのままの状態に保つだけで非表示にします。 ng-ifを使用すると、元の要素(変更ではなく元が重要)のコピーが再度表示されるときに配置されます。

フィルタリングのヒント

この記事には、リストをフィルタリングするためのいくつかの素晴らしいヒントもあります。

この方法では、データのサブリストを作成する必要がないため、ng-showを使用してフィルターで除外された要素を非表示にするのと同じです。

また、「ユーザー入力のデバウンス」と呼ばれる別の手法。最後のオプションは、ユーザーが入力を停止するまでフィルタリングを待機することです。 jsfiddleの例 を含みます。

もっと

その他のヒントは、リンクされた記事で見つけることができます。そこにもリソースがリストされているので、それは良い出発点になるはずです。最も明白な1回と素早い勝利がここにリストされています。

もう1つの素晴らしい記事は AngularJSでデータバインディングはどのように機能するのですか?

19
hcpl

少し遅れますが、これでうまくいくかもしれません:

https://github.com/Pasvaz/bindonce

変更する必要のないバインディングで使用できるため、$ digestはそれらを処理しなくなります。

13
Jesus Rodriguez

angular 1.3以上では、次を使用して一度バインドできます::他のサードパーティのjsを使用する必要はありません

<li ng-repeat="item in :: items">

これは、アイテムが変更されない場合に適しているため、一度バインドできます。

7
yonia

データグリッドコンポーネントでリスナーの数が1000を超えたときに、パフォーマンスの問題が発生しました。

React.jsを使用してビューを構築するディレクティブを使用して、この問題を解決しました。ディレクティブは更新関数を公開しました。

データが(コントローラーで)変更されるたびに、更新関数がディレクティブをトリガーし、react.jsエンジンが効率的にレンダリングを実行しました。

angularプロジェクト内で2番目の主要なフレームワークを使用することは大きなオーバーヘッドであり、これは実際のデータバインディングの魔法ではありませんが、はるかに高速に動作します。

最終的に、angular.jsの使用をやめ、react.js + FLUXに移動しました。私はその方が良いと思いますが、角度からシフトするのは簡単ではありませんが、それだけの価値があります。

react.jsを使用する角度ディレクティブ

1
doron aviguy

私はこれに数週間取り組んできました。 2つのことが大きな違いを生んでいることがわかりました。

(i)ワンタイムバインディング:可能な場合はワンタイムバインディングを使用します。 (ii)DEBOUNCE:すぐに伝播する必要はないが250ミリ秒待機できる入力の場合、デバウンス設定を設定します。これは、私の大きなng-repeatテーブルに信じられないほどの違いをもたらしました。私はデバウンス設定がどれほど効果的だったかを強調することはできません。 (ここを参照: https://docs.angularjs.org/api/ng/directive/ngModelOptions

0
Soferio

時計の数を制限することは、多くの場合長い道のりになります。時計の数を減らすのに効果的なテクニックの概要は次のとおりです

http://www.syntaxsuccess.com/viewarticle/547a8ba2c26c307c614c715e

0
TGH

bject.observe()は、ブラウザに真のデータバインディングを提供するために提案されているメカニズムです。オブジェクトおよび配列への変更を監視するメカニズムを公開し、これらのオブジェクトに加えられた変更を他のユーザーに通知します。

<!DOCTYPE html>
<html>
<head>
<base target="_blank">
<title>Object.observe()</title>

<link rel="stylesheet" href="../css/main.css" />

</head>

<body>

<div id="container">

  <h1><a href="https://shailendrapathakbits.wordpress.com/" title="code_lab_by_shail ">code_lab_by_shail</a> Object.observe()</h1>

    <p>An object <code>o</code> is created and <code>Object.observe()</code> is called on it.</p>

  <p>Three changes are made to <code>o</code> and <code>Object.observe()</code> records these changes as shown below.</p>

  <p>Use the console to find out what happens if you make further changes to <code>o</code>: it's defined in global scope.</p>

  <p>Call <code>Object.unobserve(o, observer)</code> to stop observing changes.</p>

  <p id="data" style="font-size: 14px;"></p>

  <script src="js/main.js"></script>

  <a href="https://github.com/shailendra9/objectobserver/blob/master/index.html" title="View source for this page on GitHub" id="viewSource">View source on GitHub</a>

</div>

<script src="../js/lib/ga.js"></script>

</body>
</html>
0

デバッグデータを無効にする によって一般的にパフォーマンスを向上させることもできます

0

大きなデータを含むng-gridでパフォーマンスの問題がありました。それを Angular Grid に置き換えることで解決しました。そのWebサイトのデモでは、100,000行を簡単に管理できることが示されています。

0
Ceolter