source

ngFor와 함께 trackBy를 사용하는 방법

itover 2023. 4. 27. 22:11
반응형

ngFor와 함께 trackBy를 사용하는 방법

저는 제가 무엇을 반환해야 하는지 정말 이해할 수 없습니다.trackBy웹에서 본 몇 가지 예를 바탕으로 객체에 대한 일부 속성 값을 반환해야 합니다.맞나요?내가 받아야 하는 이유index매개 변수로?

예를 들어, 다음과 같은 경우:

Component.component.ts

constructor() {
    window.setInterval(() => this.users = [
            { name: 'user1', score: Math.random() },
            { name: 'user2', score: Math.random() }
        ],
        1000);
}

userByName(index, user) {
    return user.name;
}

Component.template.html

<div *ngFor="let user of users; trackBy:userByName">
  {{user.name}} -> {{user.score}}
</div>

이 템플릿에 표시된 개체는 이름이 변경되지 않았음에도 불구하고 계속 업데이트됩니다. 이유는 무엇입니까?

각에ngDoCheck에트된거리에 대해 ngForOf지시문, 각도는 변경된 개체를 확인합니다.하는 방법은 다르며, 하는 방법은 각각 . trackBy현재 개체를 새 개체와 비교하는 함수입니다.은 " " 입니다.trackBy함수는 ID별로 항목을 추적합니다.

const trackByIdentity = (index: number, item: any) => item;

현재 항목을 수신하고 일부 값을 반환해야 합니다.그런 다음 함수에 의해 반환된 값을 이 함수가 마지막으로 반환된 값과 비교합니다.값이 변경되면 에서는 변경 내용을 보고합니다.따라서 기본 함수가 개체 참조를 반환하는 경우 개체 참조가 변경된 경우 현재 항목과 일치하지 않습니다.그래서 당신은 당신의 고객을 제공할 수 있습니다.trackBy다른 것을 반환하는 함수.예를 들어 개체의 일부 키 값입니다.이 키 값이 이전 키 값과 일치하면 Angular는 변경 사항을 감지하지 못합니다.

...trackBy:userByName더 이상 지원되지 않습니다.이제 함수 참조를 제공해야 합니다.다음은 기본적인 예입니다.

setInterval( () => {
  this.list.length = 0;
  this.list.push({name: 'Gustavo'});
  this.list.push({name: 'Costa'});
}, 2000);

@Component({
  selector: 'my-app',
  template: `
   <li *ngFor="let item of list; trackBy:identify">{{item.name}}</li>
  `
})
export class App {
  list:[];

  identify(index, item){
     return item.name; 
  }

개체 참조가 변경되더라도 DOM은 업데이트되지 않습니다.여기 플런커가 있습니다.어떻게 하는지 궁금하다면,ngFor후드 아래에서 작동합니다. 이 답변을 읽으십시오.

주제는 여전히 활성화되어 있고 명확한 답을 찾는 것이 어렵기 때문에 @Max의 답변 외에 몇 가지 예를 추가하겠습니다.

app.component.ts

array = [
    { "id": 1, "name": "bill" },
    { "id": 2, "name": "bob" },
    { "id": 3, "name": "billy" }
]

foo() {
    this.array = [
        { "id": 1, "name": "foo" },
        { "id": 2, "name": "bob" },
        { "id": 3, "name": "billy" }
    ]
}

identify(index, item) {
    return item.id;
}

다을표니다합시를 표시해 array용사여하를 3Div로를 .*ngFor.

app.component.vmdk

*ngFor 트랙 없음 기준:

<div *ngFor="let e of array;">
   {{e.id}} - {{e.name}}
</div>
<button (click)="foo()">foo</button>

다음을 클릭하면 어떻게 됩니까?foo추단?

3개의 디브가 새로 고쳐집니다.직접 사용해 보고 콘솔을 열어 확인합니다.

*ngFor 트랙By 포함:

<div *ngFor="let e of array; trackBy: identify">
   {{e.id}} - {{e.name}}
</div>
<button (click)="foo()">foo</button>

다음을 클릭하면 어떻게 됩니까?foo추단?

첫 번째 div만 새로 고쳐집니다.직접 사용해 보고 콘솔을 열어 확인합니다.

그리고 만약 우리가 전체 객체 대신에 첫 번째 객체를 업데이트한다면 어떨까요?

foo() {
    this.array[0].name = "foo";
}

사할필없다니습가를 사용할 .trackBy여기서.

이 기능은 도식화된 것처럼 보이는 서브스크립션을 사용할 때 특히 유용합니다.array다음과 같이 표시됩니다.

 array = [];
 subscription: Subscription;

 ngOnInit(): void {
    this.subscription = this.fooService.getArray().subscribe(data => {
       this.array = data;
    });
 }

 identify(index, item) {
    return item.id;
 }

설명서에서 다음을 참조하십시오.

이러한 비싼 작업을 피하기 위해 NgForOf.trackBy에 trackBy 옵션을 제공하여 기본 추적 알고리즘을 사용자 지정할 수 있습니다. trackBy는 인덱스와 항목이라는 두 개의 인수를 가진 함수를 사용합니다.trackBy가 지정된 경우 Angular 트랙은 함수의 반환 값에 따라 변경됩니다.

여기서 더 읽기: https://angular.io/api/common/NgForOf

여기에서 저의 원래 답변을 찾으십시오. https://stackoverflow.com/a/57890227/9753985

다음은 구성 요소 클래스에서 함수를 작성하는 번거로움 없이 반복된 모델의 속성별로 추적할 수 있도록 하기 위해 프로젝트에서 사용하는 내용입니다.

import { Host, Directive, Input } from "@angular/core";
import { NgForOf } from "@angular/common";

@Directive({
    selector: "[ngForTrackByProperty]"
})
export class TrackByPropertyDirective {

    private _propertyName: string = "";

    public constructor(@Host() private readonly _ngFor: NgForOf<any>) {
        this._ngFor.ngForTrackBy = (_: number, item: any) => this._propertyName ? item[this._propertyName] : item;
    }

    @Input("ngForTrackByProperty")
    public set propertyName(value: string | null) {
        // We must accept null in case the user code omitted the ": 'somePropName'" part.
        this._propertyName = value ?? "";
    }

}

용도:

<some-tag *ngFor="let item of models; trackByProperty: 'yourDiscriminantProp'">

app.component.vmdk

<button class="btn btn-warning" (click)="loadCourses()">LoadCourses</button>
<ul>
    <li *ngFor="let course of courses; trackBy:trackCourse">
        {{course.name}}
    </li>
</ul>

app.component.ts

loadCourses() {

    this.courses = [
    {id:1, name:'cour1'},
    {id:2, name:'cour2'},
    {id:3, name:'cour3'}
    ]  
};

trackCourse(index : number, course: any) {
    return course ? course.id : undefined;
};

언급 모스 부호 지침 섹션에서 확인할 수 있습니다.

trackBy를 사용하는 목적은 요소의 ID를 반복할 수 없도록 설정하는 것입니다.Angular가 동일한 ID를 가진 두 요소를 볼 경우 요소의 내용을 확인하기 위해 진행되며 내용이 변경된 경우에만 다시 칠됩니다.ID가 없으면 Angular는 내용이 동일한 경우에도 일반적으로 변경되는 요소의 객체 참조에 의존하므로 Angular는 다른 참조로 인해 요소를 다시 칠합니다.

이 각진NgFor문서가 도움이 될 것입니다.https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html

아래 코드 예제

<div *ngFor="let user of users; trackBy:user?.name">
 {{user.name}} -> {{user.score}}
</div>

그렇지 않으면 사용할 수 있습니다.

*ngFor="a of array; index as i;"

그리고.

[attr.data-target]="'#test' + i"

그리고.

name="test{{i}}

언급URL : https://stackoverflow.com/questions/42108217/how-to-use-trackby-with-ngfor

반응형