70

大きな配列を持つ ng-repeat があるとします。

ng-repeat が実行されると、その配列のすべての要素が分離されたスコープに追加され、配列自体がスコープに含まれます。つまり、$digest は配列全体の変更をチェックし、さらに、その配列内のすべての個々の要素の変更をチェックします。

私が話していることの例として、このプランカーを見てください。

私の使用例では、配列の要素を 1 つも変更しないため、それらを監視する必要はありません。配列全体のみを変更します。その場合、ng-repeat はテーブル全体を再レンダリングします。(私がこれについて間違っている場合は、私に知らせてください..)

(たとえば)1000行の配列では、評価する必要のない1000以上の式です。

メイン配列を見ながらウォッチャーから各要素を登録解除するにはどうすればよいですか?

おそらく、登録を解除する代わりに、 $digest をより細かく制御して、個々の行をスキップすることができますか?

この特定のケースは、実際にはより一般的な問題の例です。$watch が「登録解除」関数を返すことは知っていますが、ほとんどの場合、ディレクティブがウォッチを登録している場合は役に立ちません。

4

5 に答える 5

89

すべてのアイテムを監視するために監視しない大きな配列を持つリピーターを持つこと。

1 つの引数と配列への式を受け取るカスタム ディレクティブを作成する必要があります。次に、リンク関数でその配列を監視するだけで、リンク関数にプログラムで HTML を更新させることができます ( ng-リピート)

(疑似コード) のようなもの:

app.directive('leanRepeat', function() {
    return {
        restrict: 'E',
        scope: {
           'data' : '='
        },
        link: function(scope, elem, attr) {
           scope.$watch('data', function(value) {
              elem.empty(); //assuming jquery here.
              angular.forEach(scope.data, function(d) {
                  //write it however you're going to write it out here.
                  elem.append('<div>' + d + '</div>');
              });
           });
        }
    };
});

...お尻の痛みのようです。

代替のハック手法

ループして、削除したい式と一致するかどうか$scope.$$watchersを調べてから、簡単な呼び出しで削除できる場合があります。ここでの PITA は、タグ間のようなものが式になり、キャリッジ リターンも含まれるということです。$scope.$$watchers[0].exp.expsplice()Blah {{whatever}} Blah

利点として、ng-repeat の $scope をループしてすべてを削除し、必要なウォッチを明示的に追加することができる場合があります...わかりません。

いずれにせよ、それはハックのようです。

$scope.$watch によって作成されたウォッチャーを削除するには

呼び出し$watchによって返された関数でa の登録を解除できます。$watch

たとえば、一$watch度だけ発火させるには:

var unregister = $scope.$watch('whatever', function(){ 
     alert('once!');
     unregister();
});

もちろん、いつでも登録解除機能を呼び出すことができます...これは単なる例です。

結論:あなたが求めていることを正確に行うための素晴らしい方法は本当にありません

しかし、考慮すべきことが 1 つあります。心配する価値があるのでしょうか。さらに、何千ものレコードをそれぞれ数十の DOMElement にロードすることは本当に良い考えでしょうか? 思考の糧。

それが役立つことを願っています。


EDIT 2(悪い考えを削除)

于 2012-11-30T19:53:01.037 に答える
16

$watch は、呼び出されたときに $watch のバインドを解除する関数を返します。したがって、これが「watchOnce」に必要なすべてです。

var unwatchValue = scope.$watch('value', function(newValue, oldValue) {
  // Do your thing
  unwatchValue();
});
于 2016-02-22T18:07:50.353 に答える
3

bindonceにディレクティブを追加できますng-repeathttps://github.com/pasvaz/bindonceからダウンロードする必要があります。

編集:いくつかの注意事項:

テンプレートで補間を使用している場合は{{}}、それを に置き換える必要があります<span bo-text>

ディレクティブを使用している場合は、それらを正しいディレクティブng-に置き換える必要があります。bo-

また、同じ要素にbindonceと を配置している場合は、 を親要素に移動するか ( https://github.com/Pasvaz/bindonce/issues/25#issuecomment-25457970を参照)、または に追加してみてください。ng-repeatbindoncetrack byng-repeat

于 2013-11-25T14:20:50.207 に答える
2

angularjs 1.3以上を使用している場合は、シングル バインド構文を次のように使用できます。

<li ng-repeat="item in ::contents">{{item}}</li>

これにより、値がバインドされ、最初のダイジェスト サイクルが実行され、値が からundefineddefined初めて変更されると、ウォッチャーが削除されます。

これに関する非常に役立つブログ

于 2016-01-31T08:29:33.103 に答える