2

*ngFor用来迭代一些这样的数据:

<div *ngFor="let d of [1, 2, 3]"> {{d}} </div>

一切都很好,我得到了预期的结果:

<div> 1 </div>
<div> 2 </div>
<div> 3 </div>

然后,我想知道我是否使用函数而不是{{d}},所以我写了一个函数:

protected logAndReturn(item) {
    console.log(item);
    return item;
}

我用它:

<div *ngFor="let d of [1, 2, 3]"> {{logAndReturn(d)}} </div>

我得到了与第一个代码相同的渲染 HTML 结果,但控制台输出不是我的预期输出。控制台输出:

1
2
3
1
2
3

Angular is running in the development mode. Call enableProdMode() to enable the production mode.

1
2
3
1
2
3

添加的函数现在被调用了 12 次(每个项目 4 次)

这是您可以自己测试的代码:jsfiddle

我的代码错了吗?有什么解决方案可以防止这些额外的电话吗?为什么会发生这种情况,有人可以解释一下吗?

4

2 回答 2

3

此问题与 无关,是内插*ngFor的正常行为。Angular 多次故意调用它以检查是否已更改。插值用于获取(打印),不推荐用于调用。它会不必要地开火。expression({{ }})expressionexpressionsmethods

问题在于插值内部的方法不是 *ngFor

于 2018-06-09T10:54:36.847 回答
1

在视图中使用方法与使用不纯管道相同。这段代码将在视图上的每个事件中执行,可能会执行很多次。在我们的示例中,该logAndReturn()方法仅返回一个数字,因此可以假设在视图中运行它,但如果它会执行更复杂的操作,则可能是一个很大的性能问题。使用一个简单的程序,您可以检查 console.log 以查看“logAndReturn”的跟踪是在哪一步打印的。这是新组件的外观:

export class AppComponent implements 
OnChanges,
OnInit,
DoCheck,
AfterContentInit,
AfterContentChecked,
AfterViewInit,
AfterViewChecked,
OnDestroy
{
  private var01: string = "default value";
  constructor( private trans: TranslatorService ){}
  ngOnChanges (){
     console.log('Trace OnChanges');
  }
  ngOnInit (){
     console.log('Trace onInit');
  }
  ngDoCheck (){
     console.log('Trace doCheck');
  }
  ngAfterContentInit(){
     console.log('Trace After Content Init');
  }
  ngAfterContentChecked(){
     console.log('Trace after contente checked');
  }
  ngAfterViewInit(){
     console.log('Trace after view init');
  }
  ngAfterViewChecked(){
     console.log('Trace after view checked');
  }
  ngOnDestroy(){
     console.log('Trace on destroy');
  }
  testRender() {
    console.log('trace 01');
    return 'This is a test that runs a console log'
  }
  (...)
}

要深入了解这里真正发生的事情,请阅读有关生命周期的 Angular 2 官方文档

于 2018-06-09T11:05:49.813 回答