【问题标题】:Angular 2 *ngFor performance issue with select/optionAngular 2 *ngFor 选择/选项的性能问题
【发布时间】:2017-05-01 18:18:52
【问题描述】:

我正在使用*ngFor 填充options<select></select>。我的问题是我的 6 个 <select> 中的 1 个可以有 1000 数组值。性能是痛苦的。我知道这是因为changeDetectionOne-way Binding。有没有办法更好地为<option> 实现*ngFor。我实际上不需要change detectionone-way binding

我的代码

<select [formControl]="requestForm.controls['SellCommodityId']">
   <option [value]="" disabled selected>COMMODITY/GRADE</option>
   <option [value]="item.Id" *ngFor="let item of fieldOptions?.Product;">{{item.Value}}</option>                
</select>

2016 年 12 月 20 日更新

我将选择放入它的一个组件中,如下所示:

import { Component, ChangeDetectionStrategy,Input } from '@angular/core';
/**
 * <ihda-select [list]="list" [control]="control" [titleOption]="title"></ihda-select>
 */
@Component({
  selector:'ihda-select',
  changeDetection:ChangeDetectionStrategy.OnPush,
  template:`
    <select [formControl]="control" class="form-control">
       <option [value]="" disabled selected>{{titleOption}}</option>
       <option [value]="item.Id" *ngFor="let item of list">{{item.Value}}</option>                
     </select>
  `,
  styleUrls: ['../app.component.css']
})
export class IHDASelect{
    @Input() list: any[];
    @Input() control: any;
    @Input() titleOption: string;
}

性能问题仍然存在。

似乎不是changeDetection,因为我尝试&lt;select&gt; 中删除[formControl] 属性,然后不再出现性能问题。似乎使用用于跟踪表单组的[formControl] 属性会导致性能问题。有这方面的信息吗?或者我该如何解决?

2016 年 12 月 21 日更新

这里的 plunker 中显示的性能问题:

https://plnkr.co/edit/2jNKFotBRIIytcmLto7y?p=preview

如果您点击Options Route,加载选项需要很长时间。如果您删除表单代码,则路由不会花费很长时间来加载。

【问题讨论】:

  • 听起来可能值得报告错误(需要允许重现的 Plunker)
  • @GünterZöchbauer 好的,我会尝试在 plunkr 中重现错误
  • @GünterZöchbauer 我添加了一个 plunker 来显示行为
  • 性能问题是如何实现的?我不知道预期的行为是什么。当我导航到选项时,会有一些延迟(大约 2 秒),我猜在启用内置输出和 prodMode 后可能会变得更快。你有没有尝试过?你试过什么浏览器?
  • 只是一个想法。我试图将选项的呈现延迟到选择获得焦点时。也不完美,但也不算太差,在 prodMode 和 AoT plnkr.co/edit/KRgYHktFXHyPugS3nPQk?p=preview IE 中会快很多,所以测试应该显示最坏的情况。

标签: angular angular2-directives


【解决方案1】:

When the Options route is selected all &lt;options&gt; for all &lt;select&gt; are rendered in one go before the application responds again.

为了避免 &lt;options&gt; 的渲染可能会延迟,以便它们仅按需渲染

<select [formControl]="control" class="form-control" (focus)="hasFocus = true">
   <option [value]="" disabled selected></option>
   <ng-container *ngIf="hasFocus">
     <option [value]="item.id" *ngFor="let item of list">{{item.value}}</option>                
   </ng-container>
</select>

https://plnkr.co/edit/KRgYHktFXHyPugS3nPQk?p=preview

该策略可以进一步优化,以便将hasFocus 设置为true,在组件已经一次显示一个&lt;select&gt; 之后延迟一个计时器,以便在浏览器空闲时它已经呈现&lt;option&gt;s.

【讨论】:

  • 不客气 :) 很高兴听到这解决了您的问题。
  • 好的,这个固定的性能,但另一个问题随之而来。我有一个按钮,单击该按钮可以使用正确的值自动填充字段。当我单击按钮时,它会选择适当的值,但在选择中看不到该值。一旦我单击下拉列表,它就会显示该值。预填充在添加焦点之前正在工作,我能做些什么来完成这项工作吗?
  • 在这种情况下,您需要在分配值之前设置hasFocus,或者在分配值时让组件本身设置hasFocus = true。您可能需要注入 constructor(private cdRef:ChangeDetectorRef) {} 并在 hasFocus = true 之后调用 this.cdRef.detectChanges() 以确保在分配值之前呈现选项。
  • 你能把这个功能添加到plunker吗?如果可能的话,将不胜感激?它对我不起作用,所以我可能会遗漏一些东西
  • 你能补充你在之前评论中解释的内容吗,然后我会看看添加我的部分。
【解决方案2】:

如果您当前组件的更改检测不是 OnPUsh ,您可以将此选择包装在一个组件中并将其设置为 OnPush 并将产品列表传递给它以供使用。

@Component({

  selector:'my-select',
  changeDetection:ChangeDetectionStrategy.OnPush,
  inputs:['list','control'],
  template:`
    <select [formControl]="control">
       <option [value]="" disabled selected>COMMODITY/GRADE</option>
       <option [value]="item.Id" *ngFor="let item of list">{{item.Value}}</option>                
     </select>

  `
})

export class MySelectCompoent{

}

然后使用它:

   <my-select [control]='requestForm.controls['SellCommodityId']' [list]='fieldOptions?.Product'></my-select>

那么谁提供列表,如果想要更新它,应该替换它。

【讨论】:

  • 所以这将有助于提高性能,因为它只会打印一次值并且不会对每个选项进行更改检测?
  • 有没有办法在不创建新组件的情况下做到这一点?我的FormGroup 在提交时是否仍会选择表单控件?
  • 是的,您正在隔离您的选择组件,这就是 angular2 的全部内容(组件),
  • 就像我说的,你可以改变你当前组件的变化检测,结果是一样的
  • 我仍然遇到性能问题,我要发布一个小提琴
猜你喜欢
  • 2018-05-13
  • 2018-09-29
  • 1970-01-01
  • 1970-01-01
  • 2016-08-02
  • 2017-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多