angular - 存在性能问题的选项卡内容

标签 angular typescript ngfor

我正在尝试使用 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);
    });
   }
}

  • 我的 operador.service.ts
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);
  }
}

编辑 2:

我编辑了这个方法来做过滤器:

  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;
      });

  }

但性能问题仍然存在......

最佳答案

从文档中,您可以使用延迟加载来增强初始化阶段:

https://material.angular.io/components/tabs/overview#lazy-loading

Lazy Loading
By default, the tab contents are eagerly loaded. Eagerly loaded tabs will initalize the child components but not inject them into the DOM until the tab is activated.

If the tab contains several complex child components or the tab's contents rely on DOM calculations during initialization, it is advised to lazy load the tab's content.

Tab contents can be lazy loaded by declaring the body in a ng-template with the matTabContent attribute.

如果您仍然遇到性能问题,则必须弄清楚如何在 for 循环中使用虚拟滚动。

更新:
不知道你的filter pipe是怎么实现的,但是你要注意是纯的还是不纯的。与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>

关于angular - 存在性能问题的选项卡内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56434690/

相关文章:

javascript - 禁用 Angular 2 中的行

typescript - 有什么理由在 TypeScript 中使用静态/私有(private)静态方法吗?

javascript - Angular 访问数组中另一个 ngFor 上的 ngFor 索引

angular - @Output 事件名称的建议是什么(以防止 native 事件名称冲突)?

javascript - 在 Angular 2 中加载 jQuery 函数

typescript - 显示与 VS Code 源代码控制扩展的差异

typescript - 禁止在 TypeScript 中创建带有大括号的类对象

arrays - *ngFor - 在同一级别循环两个数组

html - 在 ngFor 生成的表中形成输入值

angular - 在 Ionic 2 应用程序中使用 Angular 2 路由器是否有意义?