【问题标题】:Angular $watch on an array of objects对象数组上的角度 $watch
【发布时间】:2014-06-05 17:16:11
【问题描述】:

假设我有一个绑定到我的范围的动物对象数组。每个对象都有一个“名称”属性和一个“声音”属性。

然后我 $watch 数组并将 objectEquality 标志设置为 true(第三个参数)。

在我看来,我使用动物数组的 ng-repeat 为每个动物创建一个按钮。然后我将点击处理函数传递给相应的动物对象。

在点击处理程序中,如果我要更新其中一只动物的名称,$watch 会获取更改,我可以在侦听器函数中处理它。

现在我遇到的问题是,如果我用新对象重新分配其中一个动物对象,而不是仅仅更改其属性,$watch 不会接受此更改。对象数组明显改变了,但我的监听器没有被调用。

以下 plunkr 是我刚刚概述的示例:

http://plnkr.co/edit/PHXq32?p=preview

【问题讨论】:

  • 你可以使用$watchCollection
  • 不起作用。这是plunkr。 plnkr.co/edit/VLlCNj?p=preview
  • 我的感觉是它正在更改对对象的引用,而 $watch 正在寻找对对象的旧引用的属性更改。不过我可能会完全离开。
  • 好吧,我之前没有注意到这一点,但是您的 changeObject 函数不会替换数组中的任何内容。它将您的 animal 变量的引用从数组中的一个对象更改为您在该函数中实例化的那个。此外,您应该首先通过在其中使用$watch 函数来发布您试图解决的问题的更广泛范围。据我从 Plunker 得知,您只是将您的 $scope.animals 分配给 $scope.result,这似乎不是很有用。

标签: javascript arrays angularjs object


【解决方案1】:

这与 AngularJS 无关 第一件事 - 永远记住 JavaScript 是 按值传递 这是什么意思?让我们分两种情况,原语,数组和对象

  1. Primitives - 您只需将值传递给函数。因此,如果您将在函数外部初始化的变量作为函数参数传递,则对函数内部的值所做的更改不会更改外部的值。

    function testPrimitive(prm){ prm = prm+1; }

    var prm = 1; testPrimitive(prm); console.log(prm) //prm will bestill 1

  2. 对象和数组 - 这里传递的值是对象的引用。所以问题出现了如何反映传递给函数的对象的更改属性,并且如果整个对象是新创建的,更改不会反映。举个例子吧。

    var foo = {id:1, name:'iamfoo'}, bar = {id:2, name:'iambar'}; //so here two objects are created lets say at some referrence in memory ref1 and ref2 and the //memory location is assigned to foo and bar

    function updateObj(o1, o2){ o1.name='changed'; //the object o1 is not newly created. its only takes the reference and updates the property. o2 = {id:3, name:'iamnew'}; // A new object is created in a reference say 'ref3' and the ref3 is assigned to o2. Note here ref1 still remains the same }

    updateObj(foo, bar); //ref1和ref2内存位置值在这里传递

    console.log(foo);//foo will be {id:1, name:'changed'} console.log(bar); //bar will be {id:2, name:'iambar'} since bar still has ref1 memory location value

在您的情况下,您传递的是在数组中创建一个新对象并分配引用。一旦你在函数循环之外并且不能在任何地方使用,引用就会丢失; 在你的函数中尝试animal.name ='Billy'; animal.sound='baaaa';

一篇不错的文章:http://snook.ca/archives/javascript/javascript_pass

虽然我觉得这些看起来像是大多数人不知道或对此感到困惑的基本事物。

【讨论】:

  • 感谢您的回复。我知道原语是按值传递的,而对象是按引用传递的。但我没有意识到的是,即使对象是通过引用传递的,它也只是该引用(位置)的副本。因此,当您为该对象分配新引用时,它将不会在该函数之外持久化。
【解决方案2】:

尝试将 $index 作为参数传递给您的函数,然后执行

$scope.animals[index] = {name:'Billy', sound:'baaaa'};

应该这样做

【讨论】:

    猜你喜欢
    • 2016-10-19
    • 2017-12-04
    • 2014-03-24
    • 2016-08-05
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 2015-02-01
    • 1970-01-01
    相关资源
    最近更新 更多