ng-repeat 不更新数组 [英] ng-repeat not updating on update of array

查看:24
本文介绍了ng-repeat 不更新数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过 ng-repeat 循环渲染数据.我希望它在我更新数组时更新.从我读到的这应该会自动发生,但是这不起作用.那我做错了什么?

html:

<td>{{data.name}}</td><td>{{data.startData}}</td><td>{{data.endData}}</td><td>{{data.differenceData}}</td></tr>

控制器(这个功能是通过 ng-click 在按钮上触发的):

$scope.getDifferences = function () {$scope.dataDifferenceArray = [];变量 i;for (i = 0; i <20 ;i++) {$scope.dataDifferenceArray.push({姓名 : 30,起始数据:20,结束数据:2,差异数据:30})}}

Console.log 显示数组已正确更新,但我视图中的表没有更改.我不知道我做错了什么.

解决方案

那是因为您更改了方法 getDifferences 中的数组引用.

为了避免这种情况,我们使用,例如使用controller as"语法:

[...]<tr ng-repeat="c.dataDifferenceArray 中的数据"><td>{{data.name}}</td><td>{{data.startData}}</td><td>{{data.endData}}</td><td>{{data.differenceData}}</td></tr>[...]

如果你想了解范围是如何工作的,我会建议这篇文章:https://github.com/angular/angular.js/wiki/Understanding-Scopes#ngRepeat

另一种解决方案可能是:

$scope.getDifferences = function () {$scope.dataDifferenceArray.length = 0;//这里  -  -变量 i;for (i = 0; i <20 ;i++) {$scope.dataDifferenceArray.push({姓名 : 30,起始数据:20,结束数据:2,差异数据:30})}}

但在此解决方案中,您需要在外部(并且仅一次)创建数组:$scope.dataDifferenceArray = [];

Edit2:我的回答不是很清楚,让我们试着了解深层次发生了什么:

问: 为什么 ng-repeat 仍然有引用 REFERENCE1 ?

您必须记住模板中不仅有 1 个范围.

例如:ng-repeat 指令为每个重复的元素创建新的作用域,但我们仍然可以访问每个子作用域中的父作用域.Angular 使用Prototype Inheritance 实现了这种行为:由于其原型,每个子作用域都继承其父作用域的属性.

您可以通过检查子元素上的一个来试验它是如何工作的,然后在控制台中输入:$($0).scope()(它将为您提供所选元素的范围, $0 是被选元素 (Chrome)).你现在可以看到 $($0).scope().$parent$($0).scope().__proto__ 中有相同的对象,它是您的父范围.

但是原型继承有一个问题:假设我们有 A = {};B = {C: 1},如果A继承自B,则A.C == 1.但是如果我们影响一个新值A.C = 2,我们没有改变B,只有A.

Angular 表达式使用当前范围作为 this 进行计算.所以如果我们有类似 ng-click="dataDifferenceArray = []" 的东西,它等价于 this.dataDifferenceArray = []thisng-click 所在元素的范围.

当您使用 controller-as 时,这个问题就解决了,因为它在作用域中注入了控制器,并且您永远不会直接影响作用域的属性.

让我们收回我们的例子:A = {};B = {C: {D: 1}},如果A继承自B,则A.C.D == 1.现在即使我们影响了一个新值 A.C.D = 2,我们也改变了 B.

I'm rendering data through an ng-repeat cycle. And i would like it to update as I update the array. From what i read this should happen automatically however this is not working. So what am i doing wrong?

html:

<tr ng-repeat="data in dataDifferenceArray">
    <td>
      {{data.name}}
    </td>
    <td>
      {{data.startData}}
    </td>
    <td>
      {{data.endData}}
    </td>
    <td>
      {{data.differenceData}}
    </td>
</tr>

Controller (this function is triggered on a button with ng-click):

$scope.getDifferences = function () {
  $scope.dataDifferenceArray = [];
  var i;
  for (i = 0; i < 20 ;i++) {
    $scope.dataDifferenceArray.push({
      name : 30,
      startData : 20,
      endData : 2,
      differenceData : 30
    })
  }
}

Console.log reveals that the array is updated correctly, however the table in my view does not change. I don't know what i'm doing wrong.

解决方案

That's because you change the array reference in your method getDifferences.

To avoid that, us dot, for example with "controller as" syntax:

<div ng-controller="myController as c">
    [...]

    <tr ng-repeat="data in c.dataDifferenceArray">
        <td>
          {{data.name}}
        </td>
        <td>
          {{data.startData}}
        </td>
        <td>
          {{data.endData}}
        </td>
        <td>
          {{data.differenceData}}
        </td>
    </tr>
    [...]

If you want to understand how scopes work, i would advice this article : https://github.com/angular/angular.js/wiki/Understanding-Scopes#ngRepeat

Another solution could be :

$scope.getDifferences = function () {
  $scope.dataDifferenceArray.length = 0; // here ----
  var i;
  for (i = 0; i < 20 ;i++) {
    $scope.dataDifferenceArray.push({
      name : 30,
      startData : 20,
      endData : 2,
      differenceData : 30
    })
  }
}

but in this solution, you need to create the array outside (and only once) : $scope.dataDifferenceArray = [];

Edit2: My answer was not really clear, let's try to understand what is happening in deep:

Q: Why does the ng-repeat still has the reference REFERENCE1 ?

You have to remember that there is not only 1 scope in your template.

Eg: the ng-repeat directive create new scopes for each of the repeated elements, but we can still access to the parent scope in each child scope. Angular implemented this behavior using Prototype Inheritance: each child scope inherit the properties of its parent scope thanks to its prototype.

You can experiment how it is working by inspecting one on your child elements, then enter in the console: $($0).scope() (it will give you the scope of the selected element, $0 is the selected element (Chrome)). You can now see that there is the same object in $($0).scope().$parent and $($0).scope().__proto__, it is your parent scope.

But there is one problem with prototype inheritance: Let's say we have A = {}; B = {C: 1}, if A inherits from B then A.C == 1. But if we affect a new value A.C = 2, we did not change B, only A.

Angular expressions are evaluated using the current scope as this. So if we have something like ng-click="dataDifferenceArray = []" it is equivalent to this.dataDifferenceArray = [] with this being the scope of the element where ng-click is.

This problem is solved when you are using controller-as because it injects the controller in the scope and you will never directly affect a property to the scope.

Let's take back our example: A = {}; B = {C: {D: 1}}, if A inherits from B then A.C.D == 1. And now even if we affect a new value A.C.D = 2, we changed B also.

这篇关于ng-repeat 不更新数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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