2

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

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. 观看专辑列表,当更改发生时将它们保存到服务器。

问题是 $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);

请帮助我理解这一点

4

2 回答 2

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 监听器的信息:$watch at angularjs docs

于 2013-06-27T07:09:21.873 回答
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 属性仅在添加新专辑时有效。

于 2013-06-27T07:03:34.523 回答