阵列推送时Angular2刷新视图

时间:2016-03-27 11:56:10

标签: javascript arrays asynchronous angular setinterval

我似乎无法在一个通过setInterval异步操作调用的array.push函数上获取angular2视图。

代码来自此angular plunkr example of setInterval

我想做的事情如下:

import {View, Component, bootstrap, Directive, ChangeDetectionStrategy, ChangeDetectorRef} from 'angular2/angular2'

@Component({selector: 'cmp', changeDetection: ChangeDetectionStrategy.OnPush})
@View({template: `Number of ticks: {{numberOfTicks}}`})
class Cmp {
  numberOfTicks = [];
  
  constructor(private ref: ChangeDetectorRef) {
    setInterval(() => {
      this.numberOfTicks.push(3);
      this.ref.markForCheck();
    }, 1000);
  }
}

@Component({
  selector: 'app',
  changeDetection: ChangeDetectionStrategy.OnPush
})
@View({
  template: `
    <cmp><cmp>
  `,
  directives: [Cmp]
})
class App {
}

bootstrap(App);
<!DOCTYPE html>
<html>

<head>
  <title>angular2 playground</title>
  <script src="https://code.angularjs.org/tools/traceur-runtime.js"></script>
  <script src="https://code.angularjs.org/tools/system.js"></script>
  <script src="https://code.angularjs.org/tools/typescript.js"></script>
  <script data-require="jasmine" data-semver="2.2.1" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.js"></script>
  <script data-require="jasmine" data-semver="2.2.1" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine-html.js"></script>
  <script data-require="jasmine@*" data-semver="2.2.1" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/boot.js"></script>
  
  <script src="config.js"></script>
  <script src="https://code.angularjs.org/2.0.0-alpha.37/angular2.min.js"></script>
  <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>

</head>

<body>
  <app></app>
</body>

</html>

如果“numberOfTicks”只是一个数字(如plunker原始示例所示),上面的代码将正常工作,但是一旦我将其更改为数组并推送数据,它就不会更新。

我似乎无法理解为什么会这样。

以下行为类似于我在使用setInterval / setTimeout尝试使用新数据点更新angular2中的图表时遇到的问题。

感谢您的帮助。

2 个答案:

答案 0 :(得分:19)

在添加元素后,您需要更新数组的整个引用:

TEMPDIR.write(b"""B5IB6-ELAZ1-RAPY9-V8X1I-3...")

修改

DoCheck界面也可能让您感兴趣,因为它允许您插入自己的变化检测算法。

有关详细信息,请参阅此链接:

以下是一个示例:

  constructor(private ref: ChangeDetectorRef) {
    setInterval(() => {
      this.numberOfTicks.push(3);
      this.numberOfTicks = this.numberOfTicks.slice();
      this.ref.markForCheck();
    }, 1000);
  }
}

答案 1 :(得分:10)

  

如果&#34; numberOfTicks&#34;上面的代码将正常工作。只是一个数字,但一旦我将其更改为数组并推送数据,它就不会更新。我似乎无法理解为什么会这样。

这是因为数字是JavaScript基元类型,而数组是JavaScript引用类型。当Angular更改检测运行时,它使用===来确定模板绑定是否已更改。

如果{{numberOfTicks}}是基本类型,===会比较当前值和以前的值。因此值01不同。

如果{{numberOfTicks}}是引用类型,则===会比较当前和以前的(引用)值。因此,如果数组引用没有改变,Angular将无法检测到更改。在您的情况下,使用push(),数组引用不会更改。

如果您在模板中添加以下内容

<div *ngFor="#tick of numberOfTicks">{{tick}}</div>

然后Angular将更新视图,因为存在与每个数组元素的绑定,而不仅仅是数组本身。因此,如果新项目为push(),或者删除或更改了现有项目,则会检测到所有这些更改。

因此,在您的图表plunker中,当fromto数组的内容发生更改时,以下内容应该更新:

<span *ngFor="#item of from">{{item}}</span>
<span *ngFor="#item of to">{{item}}</span>

好吧,如果每个项目都是基本类型,它会更新。