Angular 2+ ngFor с таблицами данных и NGBTypeaheads [Производительность] - PullRequest
0 голосов
/ 06 марта 2019

В настоящее время я разрабатываю веб-приложение, которое позволяет пользователям изменять параметры своего центра затрат как Администратор.

Недавно я прошел онлайн-урок Angular и вскоре понял, что я реализовал все в одном компоненте (который не является угловым).

Итак, я разделил свое приложение на несколько компонентов:

  • APP
  • Заголовок
  • Сообщения
  • CostcenterTable
  • CostcenterRow

У меня есть 2 разные службы, которые загружают данные с помощью RESTCalls.

У таблицы CostcenterTable есть ngFor (по сравнению с центрами затрат из Service), и она генерирует различные позиции.

Каждая строка имеет 6 полей, они являются полями ввода, из которых 4 активны.4 поля ввода настроены с помощью NGBTypeahead.

Проблема в том, что, если я загружаю около 30 центров затрат (30 строк), каждый раз, когда я щелкаю где-нибудь GUI (событие клика), вся таблица имеет ОДНУ задержку.

Я пытался понять, почему .. Например, если я использую ngFor с TrackBy, метод TrackBy вызывается несколько раз после каждого события, для каждой строки / поля ввода.Я предполагаю, что это может быть проблемой отставания здесь.

Не должен ли TrackBy помешать ngFor для воссоздания всего после каждого события Zone?

Я также пытался реализовать различные методы ChangeDetectionStategy, например так (и другие ..): - APP (отсоединено) - CostcenterTable (onPush) --- CostcenterRow (onPush)

НоЯ все еще не могу помешать ngFor проверять все после каждого события.

Если я использую обычные поля ввода (без [NgbTypeahead]), лаг значительно уменьшается по всей таблице, но это не решает мою проблему.

Я не очень хорошо понимаю, как это должно быть структурировано, чтобы не отставать.

Вот код:

[APPComponentHtml]:

<app-header [message]="message" [status]="status"></app-header>

<div class="pvContainer">
    <app-messages [message]="message"></app-messages>
</div>

<div class="pvContainer" *ngIf="costcenter">
    <app-costcentertable [costcenter]="costcenter" [rows]="rows" [captions]="captions"></app-costcentertable>
</div>

[CostcenterTableHtml]:

<div>
    <h1>Costcenter Administration</h1>
</div>

<table class="accTable accTableBg table table-bordered tableCostcenter">
    <thead class="tableHeadHide">
        <tr>
            <ng-container *ngFor="let caption of captions">
            <th id="colRowNr" *ngIf="caption.row =='#'">{{caption.caption}}</th>
            <th id="colNr" *ngIf="caption.row =='NR'">{{caption.caption}}</th>
            <th id="colDesc" *ngIf="caption.row =='DESCRIPTION'">{{caption.caption}}</th>
            <th id="colRank" *ngIf="caption.row =='RANK1'">{{caption.caption}}</th>
            <th id="colRank" *ngIf="caption.row =='RANK2'">{{caption.caption}}</th>
            <th id="colRank" *ngIf="caption.row =='RANK3'">{{caption.caption}}</th>
            <th id="colRank" *ngIf="caption.row =='RANK4'">{{caption.caption}}</th>
            </ng-container>

        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let pos of costcenter; let i = index;"
            [hidden]="pos.deleted" app-costcenter-row [pos]="pos"
            [caption]="captions" [index]="i">
        </tr>
    </tbody>
</table>
<button class="btn btn-info" (click)="invoice.saveCostCenter()">Save</button>

[CostcenterTableComponent]:

@Component({
  selector: 'app-costcentertable',
  templateUrl: './costcentertable.component.html',
  styleUrls: ['./costcentertable.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})


export class CostcentertableComponent implements OnInit {

  @Input() costcenter: CostCenterWrapper;
  invoice: AllocationComponent;

  @Input() rows: string[];
  @Input() captions;

  constructor(invoice: AllocationComponent, private cd: ChangeDetectorRef) {

    this.invoice = invoice;

  }

  ngOnInit() {
    //this.cd.detach();
  }

  ngAfterViewInit() {
    //this.cd.detach();
  }

  trackRow(index: any, item: any) {
    console.log("TrackbyRow started.  Returning: " + item);
    return item;
  }

  saveCostCenter() {
    this.invoice.saveCostCenter();
  }
}

[CostcenterRowHtml]:

<td class="rowNr"><label for="tddescription" id="tddescription">#</label>
    <p>{{ index + 1 }}</p></td>

<td><label for="tddescription" id="tddescription">Nr</label><input
    type="text" [(ngModel)]="pos.number" [disabled]="true"></td>

<td><label for="tddescription" id="tddescription">Description</label><input
    type="text" [(ngModel)]="pos.name" [disabled]="true"></td>

<td><label for="tddescription" id="tddescription">Rank 1</label>
    [ngbTypeahead]="invoice.taCC" [resultFormatter]="invoice.formatterRes"
    [inputFormatter]="invoice.formatter" <input type="text"
    style="text-align: left;" [(ngModel)]="pos.responsible1.ntName"
    [required]="true"
    (ngModelChange)="invoice.formatSelection(1, 'RESP1', $event)"
    (selectItem)="invoice.formatSelection(1, 'RESP1', $event)">
    <div class="pvHint">{{pos.responsible1.name}}</div></td>

<td><label for="tddescription" id="tddescription">Rank 2</label> <input
    [ngbTypeahead]="invoice.taCC" [resultFormatter]="invoice.formatterRes"
    [inputFormatter]="invoice.formatter" type="text"
    style="text-align: left;" [(ngModel)]="pos.responsible2.ntName"
    (ngModelChange)="invoice.formatSelection(1, 'CC', $event)"
    (selectItem)="invoice.formatSelection(1, 'CC', $event)">
    <div class="pvHint">{{pos.responsible2.name}}</div></td>


<td><label for="tddescription" id="tddescription">Rank 3</label> <input
    [ngbTypeahead]="invoice.taCC" [resultFormatter]="invoice.formatterRes"
    [inputFormatter]="invoice.formatter" type="text"
    style="text-align: left;" [(ngModel)]="pos.responsible3.ntName"
    (ngModelChange)="invoice.formatSelection(1, 'CC', $event)"
    (selectItem)="invoice.formatSelection(1, 'CC', $event)">
    <div class="pvHint">{{pos.responsible3.name}}</div></td>


<td><label for="tddescription" id="tddescription">Rank 4</label> <input
    [ngbTypeahead]="invoice.taCC" [resultFormatter]="invoice.formatterRes"
    [inputFormatter]="invoice.formatter" type="text"
    style="text-align: left;" [(ngModel)]="pos.responsible4.ntName"
    [required]="true"
    (ngModelChange)="invoice.formatSelection(1, 'CC', $event)"
    (selectItem)="invoice.formatSelection(1, 'CC', $event)">
    <div class="pvHint">{{pos.responsible4.name}}</div></td>

[CostcenterRowComponent]:

@Component({
  selector: '[app-costcenter-row]',
  templateUrl: './costcenter-row.component.html',
  styleUrls: ['./costcenter-row.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class CostcenterRowComponent implements OnInit {


  @Input() index: number;
  @Input() caption;
  @Input() pos;

  invoice: AllocationComponent;

  constructor(invoice: AllocationComponent) {
    this.invoice = invoice;
  }

  ngOnInit() {
  }

}
...