27

ページグリッド(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」を無視します。これは明らかに別のトピックです)。

4

11 に答える 11

28

Angularアプリを最も高速化するためにできることは、可能な場合はそれらのバインディングを減らすことです。これを行う1つの方法は、ng-repeatsを使用するのではなく、DOM操作を使用してテーブルを構築するディレクティブを作成することです。これにより、処理する必要のある時計全体の数が減り、$digestが大幅に高速化されます。

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

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

于 2013-03-26T17:39:18.250 に答える
21

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

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

ng-gridコンポーネントはこれを実装しており、直接使用するか、テクニックを盗むために検討する価値があるかもしれません。 http://angular-ui.github.com/ng-grid/

于 2013-03-29T21:35:12.477 に答える
19

リソース

大きなリストでのangularJSのパフォーマンスに関するこの投稿には、パフォーマンス調整のためのオプションの概要が記載されています。

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

limitTo(ページネーション)でデータを削減

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

巨大なデータセット(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でバインディングを削除します

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

bindonceソリューションは、双方向バインディングを削除するだけではありません基本的に、バインドが削除される前に、値がバインドされるのを1回待機します。自分で読むのが一番です。詳細については、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つの優れた記事は、AngularJSでデータバインディングがどのように機能するかです。

于 2014-02-12T11:34:03.533 に答える
13

少し遅れますが、おそらくこれはあなたのために働きます:

https://github.com/Pasvaz/bindonce

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

于 2013-07-11T10:31:00.350 に答える
7

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

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

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

于 2014-11-23T09:03:04.227 に答える
1

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

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

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

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

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

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

于 2015-04-02T13:23:25.260 に答える
0

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

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

于 2015-02-05T22:06:34.263 に答える
0

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

于 2015-04-03T22:54:55.083 に答える
0

私はこれに数週間取り組んできました。私は2つのことが実質的な違いをもたらしたことを発見しました:

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

于 2015-04-04T19:22:41.270 に答える
0

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>
于 2015-08-18T05:48:20.517 に答える
0

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

于 2017-10-20T11:32:32.207 に答える