$watch, $watchCollection, $watchGroup的使用

官方文檔

$watch簡單使用

$watch是一個scope函數,用於監聽模型變化,當你的模型部分發生變化時它會通知你。angularjs

$watch(watchExpression, listener, objectEquality);api

每一個參數的說明以下:數組

watchExpression:監聽的對象,它能夠是一個angular表達式如'name',或函數如function(){return $scope.name}。數據結構

listener: 當watchExpression變化時會被調用的函數或者表達式,它接收3個參數:newValue(新值), oldValue(舊值), scope(做用域的引用)函數

objectEquality:是否深度監聽,若是設置爲true,它告訴Angular檢查所監控的對象中每個屬性的變化. 若是你但願監控數組的個別元素或者對象的屬性而不是一個普通的值, 那麼你應該使用它性能

舉個例子:測試

$scope.name = 'hello';

var watch = $scope.$watch('name',function(newValue,oldValue, scope){
    console.log(newValue  + ' - ' + oldValue);
});

//1秒後改變name變量的值

$timeout(function(){
  $scope.name = "world";
},1000);

如何註銷$watch

太多的$watch將會致使性能問題,$watch若是再也不使用,咱們最好將其釋放掉。ui

$watch函數返回一個註銷監聽的函數,若是咱們想監控一個屬性,而後在稍後註銷它,可使用下面的方式:this

    var counter = 0;
    var watch = $scope.$watch('name',function(newValue,oldValue, scope){
        console.log('new:' + newValue + ' old:' + oldValue);
        counter ++;
        //超出中止註銷watch
        if (counter > 5 ) {
          watch();
        }
    });

$watchGroup(watchExpressions, listener);

watchExpressions是數組類型spa

若是要監聽多個變量就要寫不少個watch,這顯然不是很好的做用。

使用$watchGroup可同時監聽多個變量,若是任一一個變量發生變化就會觸發listener。

$scope.teamScore = 0;
$scope.time = 0;
$scope.$watchGroup(['teamScore', 'time'], function(newVal, oldVal) { 
if(newVal[0] > 20){ 
  $scope.matchStatus = 'win'; 
} 
else if (newVal[1] > 60){
  $scope.matchStatus = 'times up';
});

$watchCollection(obj, listener);

Shallow watches the properties of an object and fires whenever any of the properties change (for arrays, this implies watching the array items; for object maps, this implies watching the properties). If a change is detected, the listener callback is fired.

針對對象屬性的淺層監視(Shallow Watch),當屬性發生變化時觸發(對於數組,指的是監視數組的元素;對於字典對象,指的是監視其屬性) 觸發listener的回調操做。

其實徹底可使用$watch,這裏是對性能的考慮。

關於這三個方法的 在線例子 

另外注意的是這三個方法貌似是1.3版本以後才加入的。

stackoverflow上有人作了對比,我測試了幾個是正確的。

$watch() will be triggered by:

$scope.myArray = []; $scope.myArray = null; $scope.myArray = someOtherArray;

$watchCollection() will be triggered by everything above AND:

$scope.myArray.push({}); // add element $scope.myArray.splice(0, 1); // remove element $scope.myArray[0] = {}; // assign index to different value

$watch(..., true) will be triggered by EVERYTHING above AND:

$scope.myArray[0].someProperty = "someValue";

JUST ONE MORE THING...

$watch() is the only one that fires when an array is replaced with another with the same exact content. For example:

$scope.myArray = ["Apples", "Bananas", "Orange" ]; var newArray = []; newArray.push("Apples"); newArray.push("Bananas"); newArray.push("Orange"); $scope.myArray = newArray;

Below is a link to an example JSFiddle that uses all the different watch combinations and outputs log messages to indicate which "watches" were triggered:

http://jsfiddle.net/luisperezphd/2zj9k872/

我的總結:

1. $watchGroup 的第一個參數要傳數組,$watchCollection的第一個參數要傳對象

2. 監視對象和數組並且監視層次不是特別深,優先使用$watchCollection, $watchCollection能夠方便的監視數組的插入,移除。

3. 要同時監視多個變量並執行同一邏輯使用$watchGroup

4. 除此通常狀況下使用$watch,若是你知道數據結構的深度,能夠直接這樣監視。 當第三個參數true,表示深度監測,若是watch的變量比較複雜,效率會變低。

$watch('user.data', (newVal, oldVal) => {
  if(newVal !== oldVal) {

   }
})

參考:

http://stackoverflow.com/questions/26535415/angularjs-watch-vs-watchcollection-which-is-better-for-performance

http://blog.csdn.net/dm_vincent/article/details/51620193

http://blog.csdn.net/u010451286/article/details/50635839

相關文章
相關標籤/搜索