2013-10-18 83 views
294

我想觀察字典中的更改,但由於某種原因,不會調用觀看回調。

下面是我用一個控制器:

function MyController($scope) { 
    $scope.form = { 
     name: 'my name', 
     surname: 'surname' 
    } 

    $scope.$watch('form', function(newVal, oldVal){ 
     console.log('changed'); 
    }); 
} 

這裏是提琴:http://jsfiddle.net/Y8ByG/

我希望$手錶回調被解僱每次名字或姓氏更改,但它不會發生。

什麼是正確的做法?

+1

可能重複[如何深觀看angularjs數組?](http://stackoverflow.com/questions/14712089/how-to-深入觀察數組角度js) – lort

回答

530

呼叫$watchtrue作爲第三個參數:

$scope.$watch('form', function(newVal, oldVal){ 
    console.log('changed'); 
}, true); 

默認情況下,比較在JavaScript中兩個複雜的物體時,它們將被用於「參考」平等,它要求如果兩個對象引用相同的檢查而不是「價值」的平等,它檢查這些對象的所有屬性的值是否相等。

Angular documentation,第三個參數是用於objectEquality

當根據angular.equals函數確定watchExpression的objectEquality == true,不等式。爲了保存對象的值以供以後比較,使用angular.copy函數。因此,這意味着觀看複雜的物體會產生不良的記憶和性能影響。

+1

這是一個很好的答案,但我想象有些時候你不想遞歸觀看一個物體 – Jason

+14

有。默認情況下,如果你不傳遞'true',那麼如果監視值是一個對象或數組,它將檢查引用是否相等。在這種情況下,你應該明確指定屬性,比如'$ scope。$ watch('form.name')''和'$ scope。$ watch('form.surname')' – rossipedia

+3

謝謝。這正是我錯過的。 Jason,你是對的 - 你並不總是希望看到遞歸對象,但在我的情況下,這正是我所需要的。 –

13

form對象沒有改變,只有name屬性是

更新小提琴:http://jsfiddle.net/ReuA8/1/

function MyController($scope) { 
$scope.form = { 
    name: 'my name', 
} 

$scope.changeCount = 0; 
$scope.$watch('form.name', function(newVal, oldVal){ 
    console.log('changed'); 
    $scope.changeCount++; 
}); 
} 
1

試試這個:

function MyController($scope) { 
    $scope.form = { 
     name: 'my name', 
     surname: 'surname' 
    } 

    function track(newValue, oldValue, scope) { 
     console.log('changed'); 
    }; 

    $scope.$watch('form.name', track); 
} 
4

之所以你的代碼沒有按沒有工作是因爲$watch默認是參考檢查。所以簡而言之,確保傳遞給它的對象是新對象。但在你的情況下,你只是修改表單對象的一些屬性而不是創建一個新的屬性。爲了使其工作,您可以通過true作爲第三個參數。

$scope.$watch('form', function(newVal, oldVal){ 
    console.log('invoked'); 
}, true); 

它會工作,但你可以用$ watchCollection這將是更有效的再$看,因爲$watchCollection會留意表單對象淺屬性。例如。

$scope.$watchCollection('form', function (newVal, oldVal) { 
    console.log(newVal, oldVal); 
}); 
-2

您必須更改$ watch ....

function MyController($scope) { 
 
    $scope.form = { 
 
     name: 'my name', 
 
    } 
 

 
    $scope.$watch('form.name', function(newVal, oldVal){ 
 
     console.log('changed'); 
 
     
 
    }); 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script> 
 
<div ng-app> 
 
    <div ng-controller="MyController"> 
 
     <label>Name:</label> <input type="text" ng-model="form.name"/> 
 
      
 
     <pre> 
 
      {{ form }} 
 
     </pre> 
 
    </div> 
 
</div>

+6

用一個與現有答案几乎完全相同的答案回答一個兩歲的問題?不酷。 –

12

性能技巧如果有人有關鍵的數據存儲服務的種類 - >值對:

如果你有一個服務叫做的數據存儲,你只要您的大數據對象發生更改,就可以更新時間戳。 這種方式,而不是深入觀察整個對象,你只是看着變化的時間戳。

app.factory('dataStore', function() { 

    var store = { data: [], change: [] }; 

    // when storing the data, updating the timestamp 
    store.setData = function(key, data){ 
     store.data[key] = data; 
     store.setChange(key); 
    } 

    // get the change to watch 
    store.getChange = function(key){ 
     return store.change[key]; 
    } 

    // set the change 
    store.setChange = function(key){ 
     store.change[key] = new Date().getTime(); 
    } 

}); 

而在一個指令你只能眼睜睜地看着時間戳改變

app.directive("myDir", function ($scope, dataStore) { 
    $scope.dataStore = dataStore; 
    $scope.$watch('dataStore.getChange("myKey")', function(newVal, oldVal){ 
     if(newVal !== oldVal && newVal){ 
      // Data changed 
     } 
    }); 
}); 
+1

我認爲值得一提的是,在這種情況下,您將失去訪問您存儲的數據的舊值的功能。 'newVal','oldVal'在這個例子中是時間戳值而不是觀察對象的值。 它不會使這個答案無效,我只是認爲這是一個缺點值得一提。 –

+0

沒錯,我主要使用這種方法,當我想加載一個複雜的數據結構作爲某些東西的源(例如某些數據的新版本)時。 如果我關心新舊值,我不會將它們存儲在大型複雜對象中,相反,我會對我關心的事情進行小型文本表示,並觀察變化或在時間戳發生變化時獲取它。 – Feco

0

對於想要觀看的改變對象的數組中的對象的人,這似乎爲我工作(因爲此頁面上的其他解決方案沒有):

function MyController($scope) { 

    $scope.array = [ 
     data1: { 
      name: 'name', 
      surname: 'surname' 
     }, 
     data2: { 
      name: 'name', 
      surname: 'surname' 
     }, 
    ] 


    $scope.$watch(function() { 
     return $scope.data, 
    function(newVal, oldVal){ 
     console.log(newVal, oldVal); 
    }, true);