如何知道哪个对象属性发生了变化? [英] how to know which object property changed?

查看:192
本文介绍了如何知道哪个对象属性发生了变化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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?

/*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);

推荐答案

由于先前的答案似乎表明AngularJS不能为您的问题提供有针对性的解决方案,所以让我提出一个使用普通JS的解决方案.

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.

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

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:

  • 要使用外部处理程序(一个完全隐藏内部数据结构,并且仅提供用于读取和写入的API的对象)
  • 使用Java风格的getSomething和setSomething方法
  • 要使用ECMAScript 5.1中引入的本机JavaScript属性获取器和设置器
  • To use an external handler (an object which hides the internal data structure completely, and only provides an API for reading and writing)
  • To use Java-style getSomething and setSomething methods or
  • To use native JavaScript property getters and setters introduced in ECMAScript 5.1

由于某种原因,我已经看到了通过前两种方法执行此操作的更多示例,但另一方面,我也看到了使用第三种方法构建的非常复杂且美观的API的示例.我将举一个使用Object.defineProperty通过第三种方法解决问题的示例:

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:

这个想法是提供一个观察器函数,然后将其称为属性设置器的一部分:

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有点像定义对象属性的复杂方法.所以通常什么时候写

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

obj.val1 = "foo";

你会写

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

即.您可以定义在读写obj.val1时要执行的操作.这使您还可以在设置程序中调用监视程序功能:

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:

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 */)
  }
})

看起来很简单,但是似乎需要很多行代码,但是您可以使用功能性编程技术和闭包来构造程序,因此编写起来实际上并不那么复杂.因此,从本质上讲,即使这看起来似乎不是"AngularJS方式",但手动实现实际上并没有太多开销.

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.

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

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

在该示例中,几乎没有将watcher函数编码为数据结构实现的一部分.但是,如果您需要在多个地方重复使用此代码,则没有什么真正阻止您使用例如扩展解决方案的. addEventListener样式的挂钩等.

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.

由于这种方法大量使用闭包,因此如果您确实要处理大量数据,则可能会涉及一些内存问题.但是,在大多数使用情况下,您不必担心此类事情.另一方面,所有基于深度平等"检查的解决方案也不是超级内存有效或快速的解决方案.

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.

这篇关于如何知道哪个对象属性发生了变化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆