Angular ngFor lifecycle

2019-02-27 08:06发布

I'm using *ngFor to iterate some data like this:

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

Everything is fine and I got the result as expected:

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

Then, I wondered if I use a function instead of {{d}}, so I wrote a function:

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

and I used it:

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

I got the same rendered HTML result as the first code, but console output wasn't my expected output. Console output:

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

The added function was called 12 times now (4 time for each item)

Here is the code that you can test it yourself: jsfiddle

Is my code wrong? Is there any solution to prevent these extra calls? Why did this happen and can anybody explain it a little?

2条回答
干净又极端
2楼-- · 2019-02-27 08:11

This issue has no relation with *ngFor, It's the normal behavior of the expression inside the interpolation ({{ }}). It is called by angular intentionally multiple times to check if the expression has changed. Interpolation is meant for fetching (printing) expressions and not recomended for calling methods. It will fire unnecessarily.

Issue is with the method inside interploation not *ngFor

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-02-27 08:15

using methods in the view is the same that using impure pipes. This code will be executed in each event on the view, which can be a lot of times. In our example, the logAndReturn() method only returns a number so it can be assumable to run it in a view but if it would do something more complex, it could be a big problem of performance. with a simple program you can check console.log to see in which step the trace of “logAndReturn” is printed. This is the look of the new component:

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'
  }
  (...)
}

To go deeper in what really is happening here, read the official documentation of Angular 2 about the life cycle

查看更多
登录 后发表回答