角度表并不总是有效

NVO*_*NVO 3 javascript angularjs

我的控制器和手表中有一些功能可以隐藏和显示我页面上的一些元素.

我最初创建了一个对象:

$scope.selectedItems = [];
Run Code Online (Sandbox Code Playgroud)

通过一些功能,我可以选择取消选择项目:

$scope.selectAllItems = function(items){
        for(var i =0; i < items.length; i++){
            items[i].selected = true;
            $scope.selectedItems.push(items[i]._id);
        }
    }

$scope.deselectAllItems = function(items){
    for(var i=0; i<items.length; i++){
        items[i].selected = false;
        $scope.selectedItems = [];
    }
}

$scope.inverseAllItems = function(items){
    $scope.selectedItems = [];
    for(var i=0; i<items.length; i++){
        items[i].selected = items[i].selected ? false : true;
        if(items[i].selected)
            $scope.selectedItems.push(items[i]._id);
    }
}

$scope.selectItem = function(item){
    console.log(item.selected);
    if(item.selected){
        console.log(item._id);
        $scope.selectedItems.push(item._id);
    }else{
        console.log("hier2");
        if($scope.selectedItems.indexOf(item._id))
            $scope.selectedItems.splice($scope.selectedItems.indexOf(item._id),1)
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一块手表 $scope.selectedItems

$scope.$watch("selectedItems", function handleSelectedItemsChange(newValue, oldValue){
    console.log("$scope.selectedItems.length", $scope.selectedItems.length);
    if($scope.selectedItems.length > 1){
        $scope.multipleSelect = true;

        $('.itemStatus').toggleClass('hidden', true);

    }else{
        $scope.multipleSelect = false;
        $('.itemStatus').toggleClass('hidden', false);
    }
})
Run Code Online (Sandbox Code Playgroud)

问题是手表并不总是被触发.在使用' inverseSelection'和' deselectAll'函数后,它总是被触发,但是在使用' selectAll'和' selectItem'(一对一选择项目)之后不会被触发,但我没有看到我推动条目的方式有任何不同在selectedItems数组中.

有人可以帮帮我吗?

小智 5

详细说明它在你提到的两个函数上发生的原因:在inverseSelectiondeselectAll函数中初始化一个新数组.

$scope.selectedItems = [];
Run Code Online (Sandbox Code Playgroud)

默认情况下,$scope.$watch仅比较对象引用,即"它是否仍然是同一个对象".它并不关心实际内容.这就是为什么在初始化一个新的空阵列时手表会激活的原因.在其他函数中,您修改已存在的数组,因此引用是相同的.对于手表来说,它是同一个物体,所以它不会发射.

正如其他人已经提到的,有两种方法可以解决它.

  1. $ scope.$ watch with objectEquality === true

$scope.$watch告诉angular 的第三个参数来比较对象的内容:

$scope.$watch("selectedItems", function handleSelectedItemsChange(newValue, oldValue){
    ...
}, true)
Run Code Online (Sandbox Code Playgroud)

当objectEquality == true时,watchExpression的不等式根据angular.equals函数确定

https://docs.angularjs.org/api/ng/type/%24rootScope.Scope#%24watch

  1. $范围.$ watchCollection

在你的情况下,这将是更好的解决方案,因为它只是"浅看"对象.这意味着它适用于数组,但不适用于嵌套对象.为了您的阵列,它是性能比使用更好$scope.$watchobjectEquality.

$scope.$watchCollection("selectedItems", function handleSelectedItemsChange(newValue, oldValue){
    ...
})
Run Code Online (Sandbox Code Playgroud)

对于数组,这意味着要观察数组项; 对于对象图,这意味着要观察属性

https://docs.angularjs.org/api/ng/type/%24rootScope.Scope#%24watchCollection