angular - Itererar över *ngFor med en statisk array av objekt uppdaterar ständigt DOM


Jag har en enkel komponent som itererar över en statisk array av objekt och visar innehållet. När denna komponent läggs till i den större applikationen visas innehållet korrekt men jag kan inte registrera några klickhändelser på den. När jag inspekterar elementet i Chrome med högerklicka -> Inspektera möts jag av body-taggen och den går inte ner på det individuella elementet som förväntat.

Genom att navigera manuellt, indikerar inspektion av elementet att komponenten ständigt uppdateras av DOM (div-taggen blinkar). Enligt min förståelse borde ingen förändring upptäckas eftersom det är en statisk array.

Att ändra objektarrayen till en enkel strängarray ['a', 'b', 'c'] beter sig som förväntat och DOM uppdateras inte.

Att lägga till ytterligare element i mallen utanför ngFor påverkas inte och uppdateras inte konstant.

Jag använder v2.4.1

Förenklad komponent

import { Component } from '@angular/core';

@Component({
	selector: 'app-ngfor-test',
	templateUrl: './ngfor-test.component.html',
	styleUrls: ['./ngfor-test.component.css']
})
export class NgforTestComponent {
	
	get items() {
		return [
			{
				'label': 'a',
				'value': 'first'
			},
			{
				'label': 'b',
				'value': 'second'
			},
			{
				'label': 'c',
				'value': 'third'
			}
		];
	}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

Mall

<div class="item-container" *ngFor="let item of items">
	<label>{{ item.label | uppercase }}</label>
	<span>{{ item.value }}</span>
</div>

Svar #1

Som @seidme nämnde kallas gettern varje gång ändringsdetektering körs, vilket kan vara ganska ofta.

get items() {
    return [
        {
            'label': 'a',
            'value': 'first'
        },
        {
            'label': 'b',
            'value': 'second'
        },
        {
            'label': 'c',
            'value': 'third'
        }
    ];
}

returnerar en ny objektinstans varje gång det kallas, vilket får ngFor att rendera om listan.

Om du ändrar det till

items = [
        {
            'label': 'a',
            'value': 'first'
        },
        {
            'label': 'b',
            'value': 'second'
        },
        {
            'label': 'c',
            'value': 'third'
        }
    ];

get items() {
  return this.items;
}

det kommer att sluta omrendera, eftersom Angular känner igen att det fick samma objektinstans och inget har förändrats och inget behöver uppdateras eller omrenderas.

Svar #2

Du skickar en getter till *ngFor-direktivet. get-syntaxen binder en objekts-egenskap till en funktion som kommer att kallas när den egenskapen slåss upp (varje gång Angular kör förändringsdetektion), vilket i ditt fall alltid returnerar ett nytt array-objekt (referens ändras), vilket tvingar Angular att åter-rendera listan.

Relaterade artiklar