168

それぞれ約 10 フィールド、約 2 MB のデータを持つ数千行の巨大なデータセットがあります。ブラウザで表示する必要があります。最も単純なアプローチ (データをフェッチして に入れ、その仕事$scopeを任せる) は問題なく動作しますが、ノードを DOM に挿入し始めると、約 30 分間ブラウザがフリーズします。ng-repeat=""この問題にどのようにアプローチすればよいですか?

1 つのオプションは、行を段階的に追加し、DOM への 1 つのチャンクの挿入が完了する$scopeのを待ってから、次のチャンクに移動することです。ngRepeatしかし、知る限り ngRepeat は「繰り返し」が終了しても報告しないため、見苦しくなります。

他のオプションは、サーバー上のデータをページに分割し、それらを複数のリクエストでフェッチすることですが、それはさらに醜いです.

のようなものを探してAngularのドキュメントを調べng-repeat="data in dataset" ng-repeat-steps="500"ましたが、何も見つかりませんでした。私はAngularの方法にかなり慣れていないので、要点を完全に見逃している可能性があります. これに関するベストプラクティスは何ですか?

4

12 に答える 12

161

私は@AndreM96に同意します。最良のアプローチは、限られた量の行のみを表示し、より高速で優れたUXを表示することです。これは、ページネーションまたは無限スクロールで実行できます。

Angular での無限スクロールは、limitToフィルターを使用すると非常に簡単です。初期制限を設定するだけでよく、ユーザーが追加のデータを要求すると (簡単にするためにボタンを使用しています)、制限を増やします。

<table>
    <tr ng-repeat="d in data | limitTo:totalDisplayed"><td>{{d}}</td></tr>
</table>
<button class="btn" ng-click="loadMore()">Load more</button>

//the controller
$scope.totalDisplayed = 20;

$scope.loadMore = function () {
  $scope.totalDisplayed += 20;  
};

$scope.data = data;

ここにJsBinがあります。

通常、携帯電話は大量のデータをスクロールするときに遅れるため、このアプローチは問題になる可能性があります。そのため、この場合はページネーションの方が適していると思います。

これを行うには、limitTo フィルターと、表示されるデータの開始点を定義するためのカスタム フィルターが必要です。

これはページネーション付きのJSBinです。

于 2013-06-27T18:42:28.593 に答える
42

大規模なデータセットでこれらの課題を克服するための最もホットな (そして間違いなく最もスケーラブルな) アプローチは、Ionic の collectionRepeat ディレクティブおよび同様の他の実装のアプローチによって具現化されています。これは「オクルージョン カリング」と呼ばれますが、次のように要約できます: レンダリングされる DOM 要素の数を、50、100、500 などの任意の (ただしそれでも高い) ページ付けされた数に制限するだけではいけません。 、ユーザーが表示できる要素のみに制限します

一般に「無限スクロール」として知られているようなことを行うと、最初のDOM 数が多少減少しますが、これらの新しい要素はすべて下部に追加されるため、2 回更新するとすぐに肥大化します。スクロールはすべて要素数に関するものであるため、スクロールはクロールになります。それについて無限のものは何もありません。

一方、collectionRepeatアプローチは、ビューポートに収まる数の要素のみを使用し、それらをリサイクルすることです。1 つの要素がビューの外に回転すると、レンダー ツリーから切り離され、リスト内の新しい項目のデータが再入力されてから、リストの反対側のレンダー ツリーに再アタッチされます。これは、作成/破棄... 作成/破棄の従来のサイクルではなく、制限された既存の要素のセットを利用して、DOM の内外に新しい情報を取得するための既知の最速の方法です。このアプローチを使用すると、真に無限スクロールを実装できます。

/hack/adapt を使用するために Ionic を使用する必要はないことに注意してくださいcollectionRepeat。それが彼らがそれをオープンソースと呼ぶ理由です。:-) (そうは言っても、Ionic チームは注目に値するかなり独創的なことを行っています。)


React で非常によく似たことを行っている優れた例が少なくとも 1 つあります。更新されたコンテンツで要素をリサイクルする代わりに、ツリー内で表示されていないものをレンダリングしないことを選択しているだけです。非常に単純な POC 実装により、少しちらつきが生じますが、5000 個のアイテムで非常に高速です...


また...他の投稿のいくつかをエコーするために、track by小さなデータセットであっても、を使用すると非常に役立ちます。必須と考えてください。

于 2015-06-12T07:35:32.620 に答える
37

これを見ることをお勧めします:

AngularJS の最適化: 1200ms から 35ms

彼らは、4 つの部分で ng-repeat を最適化することにより、新しいディレクティブを作成しました。

最適化#1: DOM 要素をキャッシュする

最適化 #2: ウォッチャーの集計

最適化 #3: 要素の作成を延期する

最適化 #4: 非表示要素のウォッチャーをバイパスする

プロジェクトは github にあります:

使用法:

1- 次のファイルをシングルページ アプリに含めます。

  • core.js
  • scalyr.js
  • slyEvaluate.js
  • slyRepeat.js

2- モジュールの依存関係を追加:

var app = angular.module("app", ['sly']);

3- ng-repeat を置き換える

<tr sly-repeat="m in rows"> .....<tr>

楽しい!

于 2015-05-31T17:23:26.430 に答える
16

トラックバイや小さなループなどの上記のすべてのヒントに加えて、これも私を大いに助けてくれました

<span ng-bind="::stock.name"></span>

このコードは、ロードされると名前を出力し、その後監視を停止します。同様に、ng-repeat の場合、次のように使用できます。

<div ng-repeat="stock in ::ctrl.stocks">{{::stock.name}}</div>

ただし、AngularJS バージョン 1.3 以降でのみ機能します。http://www.befundoo.com/blog/optimizing-ng-repeat-in-angularjs/から

于 2015-11-27T09:45:11.993 に答える
12

「追跡」を使用してパフォーマンスを向上させることができます。

<div ng-repeat="a in arr track by a.trackingKey">

より高速:

<div ng-repeat="a in arr">

参照: https://www.airpair.com/angularjs/posts/angularjs-performance-large-applications

于 2015-05-01T14:05:32.913 に答える
11

すべての行の高さが同じ場合は、仮想化 ng-repeat を確認する必要があります: http://kamilkp.github.io/angular-vs-repeat/

このデモは非常に有望に見えます (そして、慣性スクロールをサポートしています)

于 2014-04-20T00:44:45.647 に答える
7

別のバージョン @Steffomio

各アイテムを個別に追加する代わりに、チャンクごとにアイテムを追加できます。

// chunks function from here: 
// http://stackoverflow.com/questions/8495687/split-array-into-chunks#11764168
var chunks = chunk(folders, 100);

//immediate display of our first set of items
$scope.items = chunks[0];

var delay = 100;
angular.forEach(chunks, function(value, index) {
    delay += 100;

    // skip the first chuck
    if( index > 0 ) {
        $timeout(function() {
            Array.prototype.push.apply($scope.items,value);
        }, delay);
    }       
});
于 2016-07-11T23:28:05.647 に答える
-2

大規模なデータ セットと複数の値のドロップ ダウンの場合は、 よりも使用することをお勧めしng-optionsますng-repeat

ng-repeatng-options来るすべての値をループしますが、選択オプションに表示するだけなので遅いです。

ng-options='state.StateCode as state.StateName for state in States'>

よりもはるかに高速

<option ng-repeat="state in States" value="{{state.StateCode}}">
    {{state.StateName }}
</option>
于 2016-05-16T08:51:35.580 に答える