【问题标题】:Tab content with performance issue存在性能问题的选项卡内容
【发布时间】:2019-10-19 10:35:27
【问题描述】:

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

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

  }

但性能问题仍在继续......

【问题讨论】:

  • 你为什么在每个标签上重复 [(ngModel)]="searchText" ?我从未使用过 Angular Material,但它对我来说很奇怪
  • 我已经在下面更新了我的答案,你可以添加你的过滤管的代码吗?
  • 我已经更新了我的课程,感谢您的帮助!
  • 你试过延迟加载吗?
  • 是的,但是使用延迟加载单独加载页面并不能解决我的问题。我想更快地看到标签的内容......页面加载不是问题。

标签: angular typescript ngfor


【解决方案1】:

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

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

延迟加载
默认情况下,选项卡内容是急切加载的。热切地 加载的选项卡将初始化子组件但不会注入它们 进入 DOM,直到选项卡被激活。

如果选项卡包含多个复杂的子组件或选项卡的 内容在初始化时依赖 DOM 计算,建议 延迟加载选项卡的内容。

标签内容可以通过在 ng-template 中声明 body 来延迟加载 使用 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多