web-dev-qa-db-ja.com

AngularJS:DOMツリー全体を再構築せずに、動的リストでng-repeatを実行しますか?

サーバーから取得したJSON配列のデータを含むテーブル行でng-repeatを使用しています。私の目標は、変更されていないアイテムに影響を与えることなく、サーバー上でアイテムが追加、削除、または変更されるたびにリストを自動的に更新することです。最終的な実装では、これらのテーブル行には、双方向にバインドされた<input>および<select>要素も含まれ、更新をサーバーに送り返します。 <select>要素で使用可能なオプションの一部は、変更される可能性のある別のリストのng-repeatディレクティブを使用して生成されます。

これまでのところ、サーバーから新しいアレイが来るたびに(現在2秒ごとにポーリングされています)、ng-repeatリスト全体が削除され、再生成されます。これは、テキストの選択を妨害し、入力フィールドがユーザーによって現在編集されている場合でも入力フィールドを破壊し、おそらく必要以上に遅く実行されるため、問題があります。

私はjQueryとDOM操作を使用して必要なことを行う他のWebアプリを作成しましたが、コードは非常に毛深いものになり、開発には時間がかかります。私は、AngularJSとデータバインディングを使用して、コードと時間のほんの一部でこれを達成したいと考えています。

だからここに質問があります:この方法でバッキング配列を更新することは可能ですが、実際に変更されたアイテム/プロパティに対応するDOM要素のみを変更しますか?


これは、タイマーでハードコードされた配列を使用して定期的なポーリングをシミュレートする最小限のテストケースです( http://jsfiddle.net/DWrmP/ で公開されています)。要素が削除および再作成されるため、テキスト選択は500msごとにクリアされることに注意してください。

HTML

<body ng-app="myApp">
    <table ng-controller="MyController">
        <tr ng-repeat="item in items | orderBy:'id'">
            <td>{{item.id}}</td>
            <td>{{item.data}}</td>
        </tr>
    </table>
</body>

JavaScript

angular.module('myApp', []).controller(
    'MyController', [
        '$scope', '$timeout',
        function($scope, $timeout) {
            $scope.items = [
                { id: 0, data: 'Zero' }
            ];

            function setData() {
                $scope.items = [
                    { id: 1, data: 'One' },
                    { id: 2, data: 'Two' },
                    { id: 5, data: 'Five' },
                    { id: 4, data: 'Four' },
                    { id: 3, data: 'Three' }
                    ];
                $timeout(setData, 500);
            }
            $timeout(setData, 500);
        }
        ]
);
33
nitrogen

グーグルからこれを見つける人のために、以下のページはこの問題に役立つAngularJS 1.2の機能を説明しています:

http://www.bennadel.com/blog/2556-Using-Track-By-With-ngRepeat-In-AngularJS-1-2.htm


追加して編集:リンクが死んだ場合のリンクされた投稿からの最も重要な文:

新しい「トラックバイ」構文により、AngularJSにJavaScriptオブジェクトをDOMノードに関連付けるために使用するオブジェクトプロパティ(またはプロパティパス)を指定できるようになりました。つまり、「トラックバイ」関連付けが機能している限り、DOMノードを破壊せずにJavaScriptオブジェクトを交換できます。

37
dasho

私はこの記事がngRepeatの仕組みを説明していると信じています

http://www.bennadel.com/blog/2443-Rendering-DOM-Elements-With-ngRepeat-In-AngularJS.htm

したがって、オブジェクトをコレクションに保持している場合-はい(つまり、$ hashKey persist)

そうでなければ-いいえ

7
vittore

次のソリューションは最終的に自分で構築する予定ですが、まだ製品のバックログに残っています。

Ng-repeatの問題は、必要に応じてDOMからアイテムを削除し、テーブルのサイズを変更することなどを意味しますが、データが動的な場合、データが変更されてテーブルサイズが変わるため、ちらつく可能性がありますシフトしています。特に、ページ全体がまだロードされていない可能性があるため、ページング中。

このちらつきを回避するには、テーブルの行数を変更しないでください。代わりに、「表示された」データのng-repeatを持ち、必要に応じて配列に項目を追加または削除せずに変更します。

0