html - اجرای ngFor در Angular در حلقه بیپایان هنگام نمایش آرایه
من در حال حاضر تلاش میکنم یک لاگباکس برای وباپ خود بسازم. این لاگها را به صورت یک آرایه دریافت میکند و باید آنها را ردیف به ردیف در یک div نمایش دهد. من از ngFor استفاده میکنم و آرایه لاگهایم را حلقه میزنم و سپس آنها را نمایش میدهم.
مشکل من الان این است که لاگها به طور بینهایت نمایش داده میشوند، نه فقط ۵ بار (۵ عضو آرایه در لیست) همانطور که باید.
آیا کسی یک نشانه دارد که من چه چیزی را از دست دادم؟
logs.component.html
<div class="logContent">
<div class="row">
<div class="col-12" *ngFor="let log of this.logService.getLogs()">
<app-singlelog [when]="log.when" [type]="log.type" [data]="log.data"></app-singlelog>
</div>
</div>
</div>
لاگ.سرویس.ts
export class LogService {
private logArray = [];
/* private logObject = {} as Log; */
constructor(private httpservice: HttpserviceService) {
}
public getLogs(): Array<Log> {
this.httpservice.getLogs().subscribe(data => {
data.forEach(index => {
let logObject = {} as Log;
logObject.when = index.when;
logObject.type = index.type;
logObject.data = index.data;
this.logArray.push(logObject);
})
}
)
return this.logArray;
}
}
ممنون :)
پاسخ شماره ۱
از فراخوانی توابع در قالب HTML برای نمایش داده استفاده نکنید.
در عوض، تابع getLogs() را از تابع ngOnInit() در Angular فراخوانی کرده و پاسخ را در یک متغیر ذخیره کنید. سپس روی آن متغیر حلقه بزنید:
export class LogService implements OnInit {
// ...
logs = [];
ngOnInit() {
this.getLogs();
}
getLogs(): Array<Log> {
this.httpservice.getLogs().subscribe(data => {
data.forEach(index => {
let logObject = {} as Log;
logObject.when = index.when;
logObject.type = index.type;
logObject.data = index.data;
this.logArray.push(logObject);
});
// assign the variable here:
this.logs = data;
});
}
در قالب:
<div class="col-12" *ngFor="let log of logs">
<app-singlelog [when]="log.when" [type]="log.type" [data]="log.data"></app-singlelog>
</div>
دلیل این موضوع این است که انگولار تابع getLogs شما را در هر چرخه رندرینگ صفحه فراخوانی میکند. اما شما باید درخواست http را تنها یک بار، هنگام مقداردهی اولیه کامپوننت، فراخوانی کنید.
فراموش نکنید که از Observable خود لغو اشتراک کنید. ;) - اصلاح شده از نظر زیر.
پاسخ شماره ۲
شما همچنین میتوانید از رویکرد واکنشی استفاده کنید و کارهای زیر را انجام دهید:
یک بار observable را در کامپوننت خود تعریف کنید:
logs$ = this.httpservice
.getLogs()
.pipe(
shareReplay(),
map((data) => data.map(({ when, type, data }) => ({ when, type, data })))
);
با ترکیب HTML خود موارد زیر را درج کنید:
<div class="col-12" *ngFor="let log of logs$ | async">
<app-singlelog [when]="log.when" [type]="log.type" [data]="log.data"></app-singlelog>
</div>
