如何知道哪个对象属性发生了变化?

时间:2022-10-22 16:44:37

I have a map of 10 objects. Each object has 10 properties val1, ..., val10. Now to check of a specific property of a specific object in the map has changed, I would need to write $scope.$watch 100 times. How to watch an entire map/JSobject and know exactly which property has changed?

我有一个10个物体的地图。每个对象都有10个属性val1,...,val10。现在要检查地图中特定对象的特定属性是否已更改,我需要写$ scope。$ watch 100次。如何观看整个地图/ JSobject并确切知道哪个属性已更改?

/*watch individual property*/
            $scope.$watch('map[someid].val1', function(new_val, old_val)
            {
                //do something
            });

    /*watch entire object, how would this help me?*/
            $scope.$watch('map', function(new_val, old_val)
            {
                //do something
            }, true);

7 个解决方案

#1


5  

As the previous answers seem to suggest that AngularJS doesn't provide a targeted solution for your problem, let me propose one using vanilla JS.

由于之前的答案似乎表明AngularJS没有为您的问题提供有针对性的解决方案,让我提出一个使用vanilla JS。

AFAIK if you want implement a watcher of an object, you'll need a getter/setter pattern (aka. Mutator method) of some sort. I don't know anything about AngularJS, but I'm quite certain that they must be using something similar as well. There are multiple ways to implement getters and setters in JavaScript (see the Wikipedia page linked above), but in general you have three main choices:

AFAIK如果你想实现一个对象的观察者,你需要某种getter / setter模式(aka.Mutator方法)。我对AngularJS一无所知,但我很确定他们也必须使用类似的东西。有多种方法可以在JavaScript中实现getter和setter(请参阅上面链接的Wikipedia页面),但一般来说,您有三个主要选择:

  • To use an external handler (an object which hides the internal data structure completely, and only provides an API for reading and writing)
  • 使用外部处理程序(完全隐藏内部数据结构的对象,仅提供用于读写的API)

  • To use Java-style getSomething and setSomething methods or
  • 使用Java风格的getSomething和setSomething方法或

  • To use native JavaScript property getters and setters introduced in ECMAScript 5.1
  • 使用ECMAScript 5.1中引入的本机JavaScript属性getter和setter

For some reason I've seen many more examples of doing it via the first two methods, but on the other hand I've seen one example of a quite complex and beautiful API built with the third method. I'll give you an example of solving your problem via the third method, using Object.defineProperty:

出于某种原因,我已经看到了更多通过前两种方法做到这一点的例子,但另一方面我看到了一个用第三种方法构建的相当复杂和漂亮的API的例子。我将给你一个使用Object.defineProperty通过第三种方法解决问题的例子:

The idea is to provide a watcher function, which is then called as a part of a property setter:

我们的想法是提供一个观察者功能,然后将其称为属性设置器的一部分:

function watcher(objectIndex, attributeName) {
  console.log('map[' + objectIndex + '].' + attributeName + ' has changed');
}

Object.defineProperty is a little bit like a complex way to define property for an object. So when you would normally write

Object.defineProperty有点像为对象定义属性的复杂方式。所以当你正常写作时

obj.val1 = "foo";

you'll write

Object.defineProperty(obj, 'val1', {
  get: function ()         { /* ... */ },
  set: function (newValue) { /* ... */ },
  // possible other parameters for defineProperty
})

Ie. you define what you want to be done when the obj.val1 is either read and written. This gives you a possibility to also call your watcher function as a part of the setter:

IE浏览器。您可以定义在读取和写入obj.val1时要执行的操作。这使您可以将您的观察者功能称为setter的一部分:

Object.defineProperty(obj, 'val1', {
  get: function ()         { /* ... */ },
  set: function (newValue) {
    // set the value somewhere; just don't use this.val1
    /* call the */ watcher(/* with args, of course */)
  }
})

It may seem like it's quite a many lines of code for quite a simple thing, but you can use functional programming techniques and closures to structure your program so that it isn't actually so complicated to write. So in essence even though this may not seem like an "AngularJS-way" of doing things, it isn't actually too much overhead to implement by hand.

对于非常简单的事情来说,它看起来可能是相当多的代码行,但您可以使用函数式编程技术和闭包来构建程序,这样它实际上并不是那么复杂。所以从本质上讲,尽管这可能看起来不像是一种“AngularJS方式”,但实际上手工实施的开销实际上并不多。

Here's a full code example targeting your problem: http://codepen.io/cido/pen/DEpLj/

这是针对您的问题的完整代码示例:http://codepen.io/cido/pen/DEpLj/

In the example the watcher function is quite hardly coded to be a part of the data structure implementation. However if you need to re-use this code in multiple places, nothing really stops you from extending the solution with eg. addEventListener-stylish hooks or etc.

在该示例中,观察器功能很难编码为数据结构实现的一部分。但是,如果您需要在多个位置重复使用此代码,那么没有什么能阻止您使用例如扩展解决方案。 addEventListener-时尚钩子等

As this approach uses closures quite much, it may have some memory implications, if you're really handling massive amounts of data. However, in most use cases you don't have to worry about that kind of things. And on the other hand, all solutions based on "deep equality" checks aren't going to be super memory-efficient or fast ones either.

由于这种方法使用了很多闭包,如果你真的处理大量数据,它可能会有一些内存含义。但是,在大多数用例中,您不必担心这类事情。而另一方面,基于“深度相等”检查的所有解决方案也不会是超级内存效率或快速的。

#2


4  

Currently there is nothing in AngularJS to handle this for you.

目前AngularJS中没有任何内容可以帮助您处理此问题。

You will either have to implement it yourself or find a library that does it for you.

您将要么自己实现它,要么找到一个为您完成它的库。

If you want to implement it yourself using any of the built-in watcher functions there are three options:

如果您想使用任何内置的观察器功能自己实现它,有三个选项:

1. $watch with false as third parameter: Comparing for reference equality. Not an option in your case.

1. $ watch with false as third parameter:比较引用相等。在你的情况下不是一个选项。

2. $watchCollection: Will shallow watch the ten objects in your map. Not an option.

2. $ watchCollection:将浅看地图中的十个对象。不是一种选择。

3. $watch with true as a third parameter: Will compare for object equality using angular.equals. Will work for your use case.

3. $ watch with true作为第三个参数:将使用angular.equals比较对象的相等性。适用于您的用例。

Below is an example that registers a watcher for the entire map with true as the third parameter, and does the comparison manually.

下面是一个注册整个地图的观察者的示例,其中true为第三个参数,并手动进行比较。

Note: Depending on your application (number of bindings and calls to $digest for example) watching large complex objects may have adverse memory and performance implications. As this example uses another angular.copy ($watch uses at least one internally) it will impact performance even more.

注意:根据您的应用程序(绑定次数和调用$ digest),观看大型复杂对象可能会产生不良内存和性能影响。由于此示例使用另一个angular.copy($ watch至少在内部使用一个),因此会对性能产生更大影响。

$scope.map = {};

for (var i = 0; i < 3; i++) {
  $scope.map[i] = {
    property1: 'value1',
    property2: 'value2',
    property3: 'value3'
  };
}

var source = [];

var updateSource = function(newSource) {
  angular.copy(newSource, source);
};

updateSource($scope.map);

$scope.$watch("map", function(newMap, previousMap) {

  if (newMap !== previousMap) {

    for (var id in newMap) {

      if (angular.equals(newMap[id], source[id])) continue;

      var newObject = newMap[id];
      var previousObject = source[id];

      for (var property in newObject) {

        if (!newObject.hasOwnProperty(property) ||
          angular.equals(newObject[property], previousObject[property])) continue;

        var cd = $scope.changeDetection = {};

        cd.changedObjectId = id;
        cd.previousObject = previousObject;
        cd.newObject = newObject;
        cd.changedProperty = property;
        cd.previousPropertyValue = previousObject[property];
        cd.newPropertyValue = newObject[property];
      }

      updateSource(newMap);
    }
  }
}, true);

Demo: http://plnkr.co/edit/MtfJTY3D4osUtXtIcCiR?p=preview

#3


2  

I would try using this from the angular docs

我会尝试使用角度文档中的这个

$scope.$watchCollection(collection, function(newValue, oldValue) {
 //do stuff when collection changes
});

http://docs.angularjs.org/api/ng/type/$rootScope.Scope

#4


2  

$watch has a not so known third parameter, which if true, will use angular.equals() instead of using === to test for equality. Now angular.equals() does consider two object equals if any of a set of conditions is true, one of them being:

$ watch有一个不太知名的第三个参数,如果为true,将使用angular.equals()而不是使用===来测试相等性。现在angular.equals()确实考虑两个对象等于一组条件中的任何一个为真,其中一个是:

  • Both objects or values are of the same type and all of their properties are equal by comparing them with angular.equals.
  • 通过将它们与angular.equals进行比较,两个对象或值都属于同一类型,并且它们的所有属性都相同。

This is basically saying it will do a recursive (deep) comparison, which is what you need. So detecting a change in any nested property is as easy as:

这基本上是说它会进行递归(深度)比较,这就是你需要的。因此,检测任何嵌套属性的更改都非常简单:

scope.$watch('map', function (newmap,oldmap) { 
  // detect what changed manually with your own recursive function
}, true);

This won't tell you what exactly changed, so you will need to do that part yourself. Consider binding your view directly to map instead and make sure all changes happen inside the angular $digest cycle or have them happen wrapped in $apply for a much easier approach to the problem. If for your use case it is imperative that you use a $watch you can also recursively iterate the objects and set up individual watches in there.

这不会告诉你究竟发生了什么变化,所以你需要自己做这个部分。考虑将您的视图直接绑定到map,并确保所有更改都发生在角度$ digest周期内,或者让它们包含在$ apply中,以便更轻松地解决问题。如果对于您的用例,您必须使用$ watch,您还可以递归迭代对象并在那里设置单独的手表。

#5


1  

I know I'm late to the party, but I needed something similar that the above answers didn't help.

我知道我迟到了,但我需要类似的东西,上面的答案没有帮助。

I was using Angular's $watch function to detect changes in a variable. Not only did I need to know whether a property had changed on the variable, but I also wanted to make sure that the property that changed was not a temporary, calculated field. In other words, I wanted to ignore certain properties.

我使用Angular的$ watch函数来检测变量的变化。我不仅需要知道属性是否在变量上发生了变化,而且我还想确保更改的属性不是临时的计算字段。换句话说,我想忽略某些属性。

Here's the code: https://jsfiddle.net/rv01x6jo/

这是代码:https://jsfiddle.net/rv01x6jo/

Here's how to use it:

以下是如何使用它:

$scope.$watch($scope.MyObjectToWatch, function(newValue, oldValue) {

    // To only return the difference
    var difference = diff(newValue, oldValue);  

    // To exclude certain properties from being evaluated (i.e. temporary/calculated/meta properties)
    var difference = diff(newValue, oldValue, [newValue.prop1, newValue.prop2, newValue.prop3]);

    if (Object.keys(difference).length == 0) 
        return;  // Nothing has changed
    else
        doSomething();  // Something has changed

});

By examining the Object.keys(difference) array, you can see all of the properties that have changed.

通过检查Object.keys(差异)数组,您可以看到所有已更改的属性。

Hope this helps someone.

希望这有助于某人。

#6


0  

One way is to write a small function that flattens the objects now and then and forms strings. From that point, its pretty simple to compare the strings and find the point of mismatch, which is the point where the object has changed.

一种方法是编写一个小函数,然后立即展平对象并形成字符串。从那时起,比较字符串并找到不匹配点非常简单,这是对象发生变化的点。

Needless to say, all of the object properties should be exposed.

不用说,应该公开所有对象属性。

var flatten = function (key, obj) {
    var ret = '';
    $.each(obj, function (_key, val) {
        if (typeof val == 'object') {
            ret += flatten(key + '.' + _key, val);
        } else {
            ret += ((key ? key + '.' : '') + _key + ':' + val + ',');
        }
    });
    return ret;
};

Fiddle

Followed by something like:

接下来是这样的:

$scope.$watch(obj, function (now, then) {
    var nowFlat = flatten(now),
        thenFlat = flatten(then);
    compareStrings(nowFlat, thenFlat); // add custom string compare function here
}, true)

As a performance improvement, you can always cache nowFlat and use it as thenFlat when the $watch is triggered next.

作为性能改进,您可以随时缓存nowFlat并在接下来触发$ watch时将其用作thenFlat。

#7


0  

I know I'm late to the party, but I needed something similar that the above answers didn't help.

我知道我迟到了,但我需要类似的东西,上面的答案没有帮助。

I was using Angular's $watch function to detect changes in a variable. Not only did I need to know whether a property had changed on the variable, but I also wanted to make sure that the property that changed was not a temporary, calculated field. In other words, I wanted to ignore certain properties.

我使用Angular的$ watch函数来检测变量的变化。我不仅需要知道属性是否在变量上发生了变化,而且我还想确保更改的属性不是临时的计算字段。换句话说,我想忽略某些属性。

Here's the code: https://jsfiddle.net/rv01x6jo/

这是代码:https://jsfiddle.net/rv01x6jo/

Here's how to use it:

以下是如何使用它:

$scope.$watch($scope.MyObjectToWatch, function(newValue, oldValue) {

    // To only return the difference
    var difference = diff(newValue, oldValue);  

    // To exclude certain properties from being evaluated (i.e. temporary/calculated/meta properties)
    var difference = diff(newValue, oldValue, [newValue.prop1, newValue.prop2, newValue.prop3]);

    if (Object.keys(difference).length == 0) 
        return;  // Nothing has changed
    else
        doSomething();  // Something has changed

});

Hope this helps someone.

希望这有助于某人。

#1


5  

As the previous answers seem to suggest that AngularJS doesn't provide a targeted solution for your problem, let me propose one using vanilla JS.

由于之前的答案似乎表明AngularJS没有为您的问题提供有针对性的解决方案,让我提出一个使用vanilla JS。

AFAIK if you want implement a watcher of an object, you'll need a getter/setter pattern (aka. Mutator method) of some sort. I don't know anything about AngularJS, but I'm quite certain that they must be using something similar as well. There are multiple ways to implement getters and setters in JavaScript (see the Wikipedia page linked above), but in general you have three main choices:

AFAIK如果你想实现一个对象的观察者,你需要某种getter / setter模式(aka.Mutator方法)。我对AngularJS一无所知,但我很确定他们也必须使用类似的东西。有多种方法可以在JavaScript中实现getter和setter(请参阅上面链接的Wikipedia页面),但一般来说,您有三个主要选择:

  • To use an external handler (an object which hides the internal data structure completely, and only provides an API for reading and writing)
  • 使用外部处理程序(完全隐藏内部数据结构的对象,仅提供用于读写的API)

  • To use Java-style getSomething and setSomething methods or
  • 使用Java风格的getSomething和setSomething方法或

  • To use native JavaScript property getters and setters introduced in ECMAScript 5.1
  • 使用ECMAScript 5.1中引入的本机JavaScript属性getter和setter

For some reason I've seen many more examples of doing it via the first two methods, but on the other hand I've seen one example of a quite complex and beautiful API built with the third method. I'll give you an example of solving your problem via the third method, using Object.defineProperty:

出于某种原因,我已经看到了更多通过前两种方法做到这一点的例子,但另一方面我看到了一个用第三种方法构建的相当复杂和漂亮的API的例子。我将给你一个使用Object.defineProperty通过第三种方法解决问题的例子:

The idea is to provide a watcher function, which is then called as a part of a property setter:

我们的想法是提供一个观察者功能,然后将其称为属性设置器的一部分:

function watcher(objectIndex, attributeName) {
  console.log('map[' + objectIndex + '].' + attributeName + ' has changed');
}

Object.defineProperty is a little bit like a complex way to define property for an object. So when you would normally write

Object.defineProperty有点像为对象定义属性的复杂方式。所以当你正常写作时

obj.val1 = "foo";

you'll write

Object.defineProperty(obj, 'val1', {
  get: function ()         { /* ... */ },
  set: function (newValue) { /* ... */ },
  // possible other parameters for defineProperty
})

Ie. you define what you want to be done when the obj.val1 is either read and written. This gives you a possibility to also call your watcher function as a part of the setter:

IE浏览器。您可以定义在读取和写入obj.val1时要执行的操作。这使您可以将您的观察者功能称为setter的一部分:

Object.defineProperty(obj, 'val1', {
  get: function ()         { /* ... */ },
  set: function (newValue) {
    // set the value somewhere; just don't use this.val1
    /* call the */ watcher(/* with args, of course */)
  }
})

It may seem like it's quite a many lines of code for quite a simple thing, but you can use functional programming techniques and closures to structure your program so that it isn't actually so complicated to write. So in essence even though this may not seem like an "AngularJS-way" of doing things, it isn't actually too much overhead to implement by hand.

对于非常简单的事情来说,它看起来可能是相当多的代码行,但您可以使用函数式编程技术和闭包来构建程序,这样它实际上并不是那么复杂。所以从本质上讲,尽管这可能看起来不像是一种“AngularJS方式”,但实际上手工实施的开销实际上并不多。

Here's a full code example targeting your problem: http://codepen.io/cido/pen/DEpLj/

这是针对您的问题的完整代码示例:http://codepen.io/cido/pen/DEpLj/

In the example the watcher function is quite hardly coded to be a part of the data structure implementation. However if you need to re-use this code in multiple places, nothing really stops you from extending the solution with eg. addEventListener-stylish hooks or etc.

在该示例中,观察器功能很难编码为数据结构实现的一部分。但是,如果您需要在多个位置重复使用此代码,那么没有什么能阻止您使用例如扩展解决方案。 addEventListener-时尚钩子等

As this approach uses closures quite much, it may have some memory implications, if you're really handling massive amounts of data. However, in most use cases you don't have to worry about that kind of things. And on the other hand, all solutions based on "deep equality" checks aren't going to be super memory-efficient or fast ones either.

由于这种方法使用了很多闭包,如果你真的处理大量数据,它可能会有一些内存含义。但是,在大多数用例中,您不必担心这类事情。而另一方面,基于“深度相等”检查的所有解决方案也不会是超级内存效率或快速的。

#2


4  

Currently there is nothing in AngularJS to handle this for you.

目前AngularJS中没有任何内容可以帮助您处理此问题。

You will either have to implement it yourself or find a library that does it for you.

您将要么自己实现它,要么找到一个为您完成它的库。

If you want to implement it yourself using any of the built-in watcher functions there are three options:

如果您想使用任何内置的观察器功能自己实现它,有三个选项:

1. $watch with false as third parameter: Comparing for reference equality. Not an option in your case.

1. $ watch with false as third parameter:比较引用相等。在你的情况下不是一个选项。

2. $watchCollection: Will shallow watch the ten objects in your map. Not an option.

2. $ watchCollection:将浅看地图中的十个对象。不是一种选择。

3. $watch with true as a third parameter: Will compare for object equality using angular.equals. Will work for your use case.

3. $ watch with true作为第三个参数:将使用angular.equals比较对象的相等性。适用于您的用例。

Below is an example that registers a watcher for the entire map with true as the third parameter, and does the comparison manually.

下面是一个注册整个地图的观察者的示例,其中true为第三个参数,并手动进行比较。

Note: Depending on your application (number of bindings and calls to $digest for example) watching large complex objects may have adverse memory and performance implications. As this example uses another angular.copy ($watch uses at least one internally) it will impact performance even more.

注意:根据您的应用程序(绑定次数和调用$ digest),观看大型复杂对象可能会产生不良内存和性能影响。由于此示例使用另一个angular.copy($ watch至少在内部使用一个),因此会对性能产生更大影响。

$scope.map = {};

for (var i = 0; i < 3; i++) {
  $scope.map[i] = {
    property1: 'value1',
    property2: 'value2',
    property3: 'value3'
  };
}

var source = [];

var updateSource = function(newSource) {
  angular.copy(newSource, source);
};

updateSource($scope.map);

$scope.$watch("map", function(newMap, previousMap) {

  if (newMap !== previousMap) {

    for (var id in newMap) {

      if (angular.equals(newMap[id], source[id])) continue;

      var newObject = newMap[id];
      var previousObject = source[id];

      for (var property in newObject) {

        if (!newObject.hasOwnProperty(property) ||
          angular.equals(newObject[property], previousObject[property])) continue;

        var cd = $scope.changeDetection = {};

        cd.changedObjectId = id;
        cd.previousObject = previousObject;
        cd.newObject = newObject;
        cd.changedProperty = property;
        cd.previousPropertyValue = previousObject[property];
        cd.newPropertyValue = newObject[property];
      }

      updateSource(newMap);
    }
  }
}, true);

Demo: http://plnkr.co/edit/MtfJTY3D4osUtXtIcCiR?p=preview

#3


2  

I would try using this from the angular docs

我会尝试使用角度文档中的这个

$scope.$watchCollection(collection, function(newValue, oldValue) {
 //do stuff when collection changes
});

http://docs.angularjs.org/api/ng/type/$rootScope.Scope

#4


2  

$watch has a not so known third parameter, which if true, will use angular.equals() instead of using === to test for equality. Now angular.equals() does consider two object equals if any of a set of conditions is true, one of them being:

$ watch有一个不太知名的第三个参数,如果为true,将使用angular.equals()而不是使用===来测试相等性。现在angular.equals()确实考虑两个对象等于一组条件中的任何一个为真,其中一个是:

  • Both objects or values are of the same type and all of their properties are equal by comparing them with angular.equals.
  • 通过将它们与angular.equals进行比较,两个对象或值都属于同一类型,并且它们的所有属性都相同。

This is basically saying it will do a recursive (deep) comparison, which is what you need. So detecting a change in any nested property is as easy as:

这基本上是说它会进行递归(深度)比较,这就是你需要的。因此,检测任何嵌套属性的更改都非常简单:

scope.$watch('map', function (newmap,oldmap) { 
  // detect what changed manually with your own recursive function
}, true);

This won't tell you what exactly changed, so you will need to do that part yourself. Consider binding your view directly to map instead and make sure all changes happen inside the angular $digest cycle or have them happen wrapped in $apply for a much easier approach to the problem. If for your use case it is imperative that you use a $watch you can also recursively iterate the objects and set up individual watches in there.

这不会告诉你究竟发生了什么变化,所以你需要自己做这个部分。考虑将您的视图直接绑定到map,并确保所有更改都发生在角度$ digest周期内,或者让它们包含在$ apply中,以便更轻松地解决问题。如果对于您的用例,您必须使用$ watch,您还可以递归迭代对象并在那里设置单独的手表。

#5


1  

I know I'm late to the party, but I needed something similar that the above answers didn't help.

我知道我迟到了,但我需要类似的东西,上面的答案没有帮助。

I was using Angular's $watch function to detect changes in a variable. Not only did I need to know whether a property had changed on the variable, but I also wanted to make sure that the property that changed was not a temporary, calculated field. In other words, I wanted to ignore certain properties.

我使用Angular的$ watch函数来检测变量的变化。我不仅需要知道属性是否在变量上发生了变化,而且我还想确保更改的属性不是临时的计算字段。换句话说,我想忽略某些属性。

Here's the code: https://jsfiddle.net/rv01x6jo/

这是代码:https://jsfiddle.net/rv01x6jo/

Here's how to use it:

以下是如何使用它:

$scope.$watch($scope.MyObjectToWatch, function(newValue, oldValue) {

    // To only return the difference
    var difference = diff(newValue, oldValue);  

    // To exclude certain properties from being evaluated (i.e. temporary/calculated/meta properties)
    var difference = diff(newValue, oldValue, [newValue.prop1, newValue.prop2, newValue.prop3]);

    if (Object.keys(difference).length == 0) 
        return;  // Nothing has changed
    else
        doSomething();  // Something has changed

});

By examining the Object.keys(difference) array, you can see all of the properties that have changed.

通过检查Object.keys(差异)数组,您可以看到所有已更改的属性。

Hope this helps someone.

希望这有助于某人。

#6


0  

One way is to write a small function that flattens the objects now and then and forms strings. From that point, its pretty simple to compare the strings and find the point of mismatch, which is the point where the object has changed.

一种方法是编写一个小函数,然后立即展平对象并形成字符串。从那时起,比较字符串并找到不匹配点非常简单,这是对象发生变化的点。

Needless to say, all of the object properties should be exposed.

不用说,应该公开所有对象属性。

var flatten = function (key, obj) {
    var ret = '';
    $.each(obj, function (_key, val) {
        if (typeof val == 'object') {
            ret += flatten(key + '.' + _key, val);
        } else {
            ret += ((key ? key + '.' : '') + _key + ':' + val + ',');
        }
    });
    return ret;
};

Fiddle

Followed by something like:

接下来是这样的:

$scope.$watch(obj, function (now, then) {
    var nowFlat = flatten(now),
        thenFlat = flatten(then);
    compareStrings(nowFlat, thenFlat); // add custom string compare function here
}, true)

As a performance improvement, you can always cache nowFlat and use it as thenFlat when the $watch is triggered next.

作为性能改进,您可以随时缓存nowFlat并在接下来触发$ watch时将其用作thenFlat。

#7


0  

I know I'm late to the party, but I needed something similar that the above answers didn't help.

我知道我迟到了,但我需要类似的东西,上面的答案没有帮助。

I was using Angular's $watch function to detect changes in a variable. Not only did I need to know whether a property had changed on the variable, but I also wanted to make sure that the property that changed was not a temporary, calculated field. In other words, I wanted to ignore certain properties.

我使用Angular的$ watch函数来检测变量的变化。我不仅需要知道属性是否在变量上发生了变化,而且我还想确保更改的属性不是临时的计算字段。换句话说,我想忽略某些属性。

Here's the code: https://jsfiddle.net/rv01x6jo/

这是代码:https://jsfiddle.net/rv01x6jo/

Here's how to use it:

以下是如何使用它:

$scope.$watch($scope.MyObjectToWatch, function(newValue, oldValue) {

    // To only return the difference
    var difference = diff(newValue, oldValue);  

    // To exclude certain properties from being evaluated (i.e. temporary/calculated/meta properties)
    var difference = diff(newValue, oldValue, [newValue.prop1, newValue.prop2, newValue.prop3]);

    if (Object.keys(difference).length == 0) 
        return;  // Nothing has changed
    else
        doSomething();  // Something has changed

});

Hope this helps someone.

希望这有助于某人。