AngularJs - 为新添加的子属性监视对象的最有效方法是什么?

时间:2014-03-09 06:43:46

标签: angularjs

我想要查看添加到对象的新子属性的对象。这样做的正确方法是什么?我尝试通过迭代地将新对象的键与旧对象进行比较来观察对象,但是它似乎没有检测到新键。

$scope.$watchCollection("ObjectToBeWatched", function (newObj, oldObj) {
            for (newkey in newObj) {

                var found = false;

                for (oldkey in oldObj) {
                    if (newkey == oldkey) {
                        found = true;
                        console.log('found is true');
                        break;
                    };
                };
                if (found)
                {
                    console.log('found');
                    continue; //iterate the next new val

                }
                else //this key is new
                {

                    console.log(newkey);

                } 
            }; // end for newkey
        });

3 个答案:

答案 0 :(得分:2)

$scope.$watch("ObjectToBeWatched",function(newObj,oldObj){

},true);

由于您正在深入观察,因此需要将true作为最后一个参数传递给watch。 在性能注释中,深度观察对象的计算成本很高,$watchCollection不会深度观察对象,因此它具有更好的性能。说实话,如果你在手表中做的就是这些(比较),我认为它没关系,因为它看起来并不太贵。

修改 通常$watchCollection不会按照您期望的方式工作,就像在您的情况下,我已经看到$watchCollection未按预期工作的角度github存档上出现的问题。我发现$watch几乎总是有效,我在下面的插图中显示了这一点,如果你尝试使用$watchCollection它将无效。 试试这个:

  $scope.$watch("ObjectToBeWatched", function (newObj, oldObj) {
    for (var property in newObj) {
      if (!oldObj.hasOwnProperty(property)) {
        console.log("new addition is :"+ property);
      }
    }
  },true);

这也取决于您是在观看集合还是对象,我使用$watchCollection来观察对象或数组中的多个属性。 Here is a plunk展示了你需要做的事情。另请注意,如果从监视中删除true参数,则不会记录更改。关于性能的一个词,影响在很大程度上取决于你正在观察的对象有多大以及对象改变的频率,那个插件的性能开销可以忽略不计,因为对象很小,2秒很长,但你需要要查看您的特定场景,如果您要将项目添加到数组而不是对象,那么可以使用$watchCollection

答案 1 :(得分:1)

观看对象属性的最有效方法是使用$watchCollection。来自docs

  

$ watchCollection(obj,listener);   浅表的属性   任何属性更改时对象和触发(对于数组,   这意味着要观看数组项目;对于对象图,这意味着   看着这些房产)。如果检测到更改,则为侦听器   回调被解雇。

可以找到良好的教程和比较here

答案 2 :(得分:1)

$watchCollection中存在一个错误,它会返回newCollectionoldCollection的相同属性(正如您现在遇到的那样)。

请参阅以下有关此问题的问题:

您应该能够通过保留先前newCollection的副本并对其进行比较逻辑来手动检测更改(而不是依赖于Angular传入的oldCollection):

编辑:要正常使用,您需要使用oldCollection = angular.clone(newCollection),否则我们无法检测到属性更改。

var oldCollection;
$scope.$watchCollection(collection, function(newCollection){
    // TODO: Perform your checking between `newCollection` and the cached `oldCollection` values.

    // Save the 'newCollection' values for comparison next time.
    // NOTE: Make sure to clone the object so newCollection !== oldCollection.
    oldCollection = angular.copy(newCollection);
});

以下是您可以手动检测属性更改的示例:

var oldCollection = {};
$scope.$watchCollection('o', function(newCollection) {
    // Collect the new/old properties.
    var change = {
        added: {},
        deleted: {},
        changed: {}
    };

    if (oldCollection) {
        // Check newCollection and oldCollection.
        for (var i in newCollection) {
            if (oldCollection.hasOwnProperty(i)) {
                if (oldCollection[i] !== newCollection[i]) {
                    change.changed[i] = true;
                }
            } else {
                change.added[i] = true;
            }
        }

        for (var i in oldCollection) {
            if (!newCollection.hasOwnProperty(i)) {
                change.deleted[i] = true;
            }
        }
    }

    oldCollection = angular.copy(newCollection);
});