Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does ngFor directive re-render whole array on every mutation?

Tags:

Let's say we have an array of items:

items = [
    { title: 'item 1'},
    { title: 'item 2'},
    /* ... */
];

And there is a template that renders this array:

<ul>
    <li *ngFor="let item of items">{{item.title}}</li>
</ul>

Wll angular2 rerender the whole array if I add/remove items via push/splice or will it only add/remove the markup for the corresponding items? If it does updates only, then is there any difference in mutation stategies -- should I prefer push/splice over array replacing? In other words, are these two approaches equivalent in term of rendering performance:

/* 1: mutation */
this.items.push({ title: 'New Item' });

/* 2: replacement */
var newArray = this.items.slice();
newArray.push({ title: 'New Item' });

this.items = newArray;
like image 239
admax Avatar asked Feb 15 '17 08:02

admax


People also ask

What is the purpose of NgFor directive?

NgFor is a built-in template directive that makes it easy to iterate over something like an array or an object and create a template for each item. let user creates a local variable that will be available in the template.

Is NgFor a directive?

NgFor is a structural directive, meaning that it changes the structure of the DOM . It's point is to repeat a given HTML template once for each value in an array, each time passing it the array value as context for string interpolation or binding.


2 Answers

In addition to Gunter's answer, if you want to know which part of your UI is rendered/re-rendered you can with Chrome (even independent from any lib/framework) :

  • Open your debug panel
  • Menu (of debug panel) / More tools / Rendering

You should then see the following panel :

enter image description here

Toggle the Paint Flashing option on, and have some fun with your list.
If an area is flashing green, it has been painted / re-painted đź‘Ť.

EX : If you take the Plunkr in Gunter's answer : http://plnkr.co/edit/oNm5d4KwUjLpmmu4IM2K?p=preview and toggle the Paint Flashing on, add an item to the list and you'll see that previous items do not flash. (which means there's no repaint).

like image 150
maxime1992 Avatar answered Sep 21 '22 00:09

maxime1992


No , it re-renders only when the array itself is replaced by a different array instance.

update

Thanks to Olivier Boissé (see comments)

Even when a different array instance is passed, Angular recognizes if it contains the same item instances and doesn't rerender even then.

See also this StackBlitz example

If the used IterableDiffer recognizes and addition or removal at the beginning or in the middle, then an item is inserted/removed at that place without re-rendering all other items.

The animations demonstrated in Plunkers in answers of this question How can I animate *ngFor in angular 2? also demonstrate that. In fact this kind of animation was a driving factor to get this implemented this way (in addition to general optimization)

like image 41
Günter Zöchbauer Avatar answered Sep 22 '22 00:09

Günter Zöchbauer