需要帮助才能理解棱角分明的$ watch

时间:2013-06-27 06:46:51

标签: angularjs save watch

说我有一个专辑列表,用户可以添加专辑

controller.albumList = function($scope, albumService) {
    $scope.albums = albumService.query();

    $scope.$watch('$scope.albums',function(){
        $scope.albums.$save($scope.albums)
    })

    $scope.addalbum= function(){
        $scope.albums.objects.push(album);   
    }
};
  1. 从服务器获取专辑列表并显示
  2. 用户可以添加相册
  3. 观看相册列表,当更改发生时将其保存到服务器。
  4. 问题是$ watch总是被触发,我甚至没有触发addalbum方法,每次刷新页面时都会创建一个新专辑。

    我按照todeMVC angular中的代码

    这是示例代码

    var todos = $scope.todos = todoStorage.get();
    
    $scope.newTodo = '';
    $scope.editedTodo = null;
    
    $scope.$watch('todos', function () {
        $scope.remainingCount = filterFilter(todos, { completed: false }).length;
        $scope.completedCount = todos.length - $scope.remainingCount;
        $scope.allChecked = !$scope.remainingCount;
        todoStorage.put(todos);
    }, true);
    

    请帮我理解这个

2 个答案:

答案 0 :(得分:3)

这是一个解决方案:

$scope.$watch('albums', function(newValue, oldValue) {
    if (angular.equals(newValue, oldValue)) {
        return;
    }

    $scope.albums.$save($scope.albums);
}

在观察者注册观察者之后,异步调用侦听器fn(通过$ evalAsync)来初始化观察者。在极少数情况下,这是不合需要的,因为当watchExpression的结果没有改变时会调用监听器。要在侦听器fn中检测此场景,您可以比较newVal和oldVal。如果这两个值相同(===)则由于初始化而调用了监听器。

有关$ watch listener的更多信息:$watch at angularjs docs

答案 1 :(得分:1)

首先,在引用作用域的属性时,不必指定作用域对象。所以,替换:

$scope.$watch('$scope.albums', ...)

以下内容:

$scope$watch('albums', ...)

现在谈谈你的问题。每次被监视的对象/属性的值发生变化时,都会触发$watch。这甚至包括尚未分配值的情况,例如undefinednull。因此,如果您希望仅在添加新相册时才进行保存,则可以使用类似于以下内容的代码:

//Makes assumption that albums has a length property
$scope.$watch('albums.length', function () {
    //Check for invalid cases
    if ($scope.albums === undefined || $scope.albums === null) {
        return;
    }

    //Genuine cases.
    //Proceed to save the album.
});

有了这个,$watch仍然会在不需要的情况下触发,但通过检查,您可以避免在相册未更改时保存。另请注意,仅当相册对象的长度发生更改时,您的$watch才会触发。因此,如果相册本身已更新(例如更改现有相册名称),则不会触发此手表。您可以根据需要更改监视属性。此处提到的watch属性仅在添加新相册时有效。