57

$watchトリガーされない理由を理解しようとしています。これは、関連するコントローラーのスニペットです。

$scope.$watch('tasks', function (newValue, oldValue) {
    //do some stuff
    //only enters here once
    //newValue and oldValue are equal at that point
});

$scope.tasks = tasksService.tasks();

$scope.addTask = function (taskCreationString) {
    tasksService.addTask(taskCreationString);//modifies tasks array
};

私の見解でtasksは、長さが次のようにバインドされているため、明らかに正しく更新されています。

<span>There are {{tasks.length}} total tasks</span>

私は何が欠けていますか?

4

4 に答える 4

138

$watch('tasks.length', ...)またはを試してください$watch('tasks', function(...) { ... }, true)

デフォルトでは、$watchはオブジェクトの等価性をチェックしませんが、参照のみをチェックします。そのため、$watch('tasks', ...)変更されていない同じ配列参照を常に返すだけです。

更新: Angular v1.1.4 は、このケースを処理するために$watchCollection()メソッドを追加します:

Shallow はオブジェクトのプロパティを監視し、いずれかのプロパティが変更されるたびに起動します (配列の場合、これは配列項目を監視することを意味し、オブジェクト マップの場合、これはプロパティを監視することを意味します)。変更が検出されると、listenerコールバックが起動されます。

于 2013-03-12T14:20:28.617 に答える
13

@Markによる非常に良い答え。彼の答えに加えて、$watch知っておくべき機能の重要な機能が 1 つあります。

次の$watchような関数宣言を使用します。

$watch(watch_expression, listener, objectEquality)

$watch リスナー関数は、現在のウォッチ式 (あなたの場合は ) の値と以前'tasks'ウォッチの呼び出しが等しくない場合にのみ呼び出されます。Angular は、後で比較するためにオブジェクトの値を保存します。そのため、複雑なオプションを監視すると、メモリとパフォーマンスに不利な影響があります。基本的にウォッチ式の値はシンプルな方が良いです。

于 2013-03-12T17:08:30.207 に答える
3

1 次元配列の場合は、$watchCollectionを使用できます

$scope.names = ['igor', 'matias', 'misko', 'james'];
$scope.dataCount = 4;

$scope.$watchCollection('names', function(newNames, oldNames) {
  $scope.dataCount = newNames.length;
});
于 2014-10-03T10:29:10.640 に答える