我正在尝试使用ngfor和ngif制作三个标签。 它实际上可以正常工作,但是存在性能问题 看代码
<mat-nav-list class="op-content">
<h5>Listar Usuários</h5>
<input matInput [(ngModel)]="searchText" placeholder="Filtrar por nome" class="filter-input">
<mat-tab-group>
<mat-tab label="Todos" [(ngModel)]="searchText" name="todos" ngDefaultControl>
<ng-container *ngFor="let op of tboperadores | filter : searchText">
<mat-list-item>
<a matLine [routerLink]="['/operadores', op.id_operador]">
<span class="badge badge-primary"> {{op.id_operador}}</span>
Nome: {{ op.nome }} CPF: {{ op.identificacao }}</a>
</mat-list-item>
</ng-container>
</mat-tab>
<mat-tab label="Habilitados" [(ngModel)]="searchText" name="habilitado" ngDefaultControl>
<ng-container *ngFor="let op of tboperadores | filter : searchText">
<ng-container *ngIf="op.habilitado =='S'">
<mat-list-item>
<a matLine [routerLink]="['/operadores', op.id_operador]">
<span class="badge badge-primary"> {{op.id_operador}}</span>
Nome: {{ op.nome }} CPF: {{ op.identificacao }}</a>
</mat-list-item>
</ng-container>
</ng-container>
</mat-tab>
<mat-tab label="Desabilitados" [(ngModel)]="searchText" name="desabilitado" ngDefaultControl>
<ng-container *ngFor="let op of tboperadores | filter : searchText">
<ng-container *ngIf="op.habilitado=='N'">
<mat-list-item>
<a matLine [routerLink]="['/operadores', op.id_operador]">
<span class="badge badge-primary"> {{op.id_operador}}</span>
Nome: {{ op.nome }} CPF: {{ op.identificacao }}</a>
</mat-list-item>
</ng-container>
</ng-container>
</mat-tab>
</mat-tab-group>
</mat-nav-list>
<div class="loader" *ngIf="!subscription?.closed" #loading>
</div>
如您所见,每次打开新选项卡时,我都有一个ngfor。 我试图在整个页面上只放一个, 但我无法使其正常工作。
有人有意识形态如何解决?
编辑:
我的operador.component.ts
import { Component, OnInit, } from '@angular/core';
import { Operador } from './operador';
import { OperadorService } from './operador.service';
import { Subscription, Observable } from 'rxjs';
@Component({
selector: 'app-operador',
templateUrl: './operador.component.html',
styleUrls: ['./operador.component.css']
})
//export class OperadorComponent implements OnInit, PipeTransform {
export class OperadorComponent implements OnInit {
tboperadores: Operador[];
checkedOperadors: Operador[];
subscription: Subscription;
mode = 'indeterminate';
constructor(private operadorService: OperadorService) {
}
ngOnInit(): void {
this.subscription = this.getOperadores();
}
getOperadores() {
return this.operadorService.getOperadores()
.subscribe(ob => {
console.log(ob);
this.tboperadores = ob;
});
}
}
然后,我的filter.pipe.ts:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(items: any[], searchText: string): any[] {
if(!items) return [];
if(!searchText) return items;
searchText = searchText.toLowerCase();
return items.filter( it => {
return it.nome.toLowerCase().includes(searchText);
});
}
}
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Operador } from './operador';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
@Injectable({
providedIn: 'root'
})
export class OperadorService {
private operadoresUrl = '******'; // URL to web api
constructor(
private http: HttpClient
) { }
getOperadores (): Observable<Operador[]> {
return this.http.get<Operador[]>(this.operadoresUrl)
}
getOperador(id_operador: number): Observable<Operador> {
const url = `${this.operadoresUrl}/${id_operador}`;
return this.http.get<Operador>(url);
}
addOperador (operador: Operador): Observable<Operador> {
return this.http.post<Operador>(this.operadoresUrl, operador, httpOptions);
}
deleteOperador (operador: Operador | number): Observable<Operador> {
const id_operador = typeof operador === 'number' ? operador : operador.id_operador;
const url = `${this.operadoresUrl}/${id_operador}`;
return this.http.delete<Operador>(url, httpOptions);
}
updateOperador (operador: Operador): Observable<any> {
return this.http.put(this.operadoresUrl, operador, httpOptions);
}
}
EDIT2:
我已经编辑了此方法以进行过滤:
getOperadores(option): Observable<Operador[]> {
if (option == 0) {
return this.http.get<Operador[]>(this.operadoresUrl)
} else if (option == 1) {
return this.http.get<Operador[]>(this.operadoresUrl).pipe(
map((reports: Operador[]) => reports.filter(p => p.habilitado === "S"))
);
} else {
return this.http.get<Operador[]>(this.operadoresUrl).pipe(
map((reports: Operador[]) => reports.filter(p => p.habilitado === "N"))
);
}
}
并创建了这两个方法来调用构造函数:
checkedOperadores() {
return this.operadorService.getOperadores(1)
.subscribe( ob => {
console.log(ob);
this.checkedOperadors = ob;
});
}
uncheckedOperadores() {
return this.operadorService.getOperadores(2)
.subscribe( ob => {
console.log(ob);
this.uncheckedOperadors = ob;
});
}
但是性能问题仍然存在...
答案 0 :(得分:2)
从文档中,您可以使用延迟加载来增强初始化阶段:
https://material.angular.io/components/tabs/overview#lazy-loading
延迟加载
默认情况下,选项卡的内容会急切加载。热切地 加载的选项卡将激活子组件,但不会注入它们 进入DOM,直到选项卡被激活。如果选项卡包含多个复杂的子组件或选项卡的 建议内容在初始化期间依赖DOM计算 延迟加载选项卡的内容。
可以通过在ng-template中声明主体来延迟加载Tab内容 带有matTabContent属性。
如果仍然存在性能问题,则必须弄清楚如何在for循环上使用虚拟滚动。
更新:
我不知道您的过滤器管道是如何实现的,但是无论是纯管道还是不纯管道,您都必须注意。与https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe相关的问题可能会导致性能问题。
您也可以改善代码:
1-创建三个get方法,每个方法用于一种habilitado
,例如:
get habilitados() {
return tboperadores.filter(op => op.habilitado === 'S')
}
然后在ngFor中使用它并获得ngIf。
2-也许为下面的代码创建一个组件以减少代码行:
<mat-list-item>
<a matLine [routerLink]="['/operadores', op.id_operador]">
<span class="badge badge-primary"> {{op.id_operador}}</span>
Nome: {{ op.nome }} CPF: {{ op.identificacao }}
</a>
</mat-list-item>