2017-09-18 90 views
1

我有一个用Angular 4编写的视频应用程序。在这个应用程序中,用户可以添加视频和字幕,并编辑列表中的视频标题。列表中的字幕总是与视频当前播放时间同步。当视频当前时间改变时,列表视口被改变以显示当前标题。 字幕的数量始终保持不变,用户无法添加或删除项目只能编辑标题文本。 当有很多字幕(> 500)时,应用程序运行非常缓慢。 我想根据列表视口创建和销毁ngFor中的项目,但似乎要做很多工作。 是否有更好的解决方案(不使用pagging) [![Angular - ngFor性能问题

import { Caption } from './caption'; 
 

 
export class Translation { 
 
    public sourceCaption: Caption; 
 
    public targetCaption: Caption; 
 

 
    constructor(sourceCaption: Caption, targetCaption: Caption) { 
 
     this.sourceCaption = sourceCaption; 
 
     this.targetCaption = targetCaption; 
 
    } 
 

 
    get startTime() { 
 
     return this.sourceCaption && this.sourceCaption.startTime; 
 
    } 
 

 
    get endTime() { 
 
     return this.sourceCaption && this.sourceCaption.endTime; 
 
    } 
 
} 
 

 

 
export class Caption{ 
 
    public startTime: number; 
 
    public endTime: number; 
 
    public text: Array<string>; 
 
    public id: String; 
 
    public isFlag: Boolean; 
 
    public isItalic: Boolean; 
 
    public languageId: String; 
 
    public clientId: String; 
 

 
    constructor(clientId: String, languageId: String, id?: String, startTime?: number, endTime?: number, text?: Array<string>, isFlag?:Boolean, isBold?:Boolean, isItalic?: Boolean) { 
 
     this.id = id; 
 
     this.clientId = id || clientId; 
 
     this.startTime = startTime; 
 
     this.endTime = endTime; 
 
     this.text = text || new Array<string>(); 
 
     this.isFlag = isFlag; 
 
     this.languageId = languageId; 
 
    } 
 
}
<!--list--> 
 

 
<div class="tt-translations-list"> 
 
    <tt-translation-list-header></tt-translation-list-header> 
 
    
 
    <div class="tt-translation-list-items-container" #container> 
 
    <div class="tt-translation-list-item-container" 
 
     *ngFor="let translation of translations; trackBy:i; let i = index" 
 
     (click)="setEditMode(translation)"> 
 

 
     <tt-translations-list-item [index]="i" 
 
            [translation]="translation"> 
 
     </tt-translations-list-item> 
 
    </div> 
 
    </div> 
 
</div> 
 

 

 

 
<!--list-item--> 
 

 
<div class="tt-translations-list-item" 
 
    #container 
 
    [ngClass]="{'selected-row': isEditMode}"> 
 

 
    <div class="tt-translations-list-item-border-container" 
 
      [ngClass]="{'visible': isEditMode}"> 
 
    </div> 
 

 
    <div class="tt-translations-list-item-source-caption-container"> 
 
     <div class="source-caption-header"> 
 
      <tt-translations-list-item-header [caption]="translation.sourceCaption" 
 
              [index]="index"> 
 
      </tt-translations-list-item-header> 
 
     </div> 
 

 
     <div class="source-caption-content-container" 
 
      dir="auto"> 
 
      <span *ngFor="let line of translation?.sourceCaption?.text"> 
 
       {{line}} 
 
      </span> 
 
     </div> 
 
    </div> 
 

 
    <div class="tt-translations-list-item-target-caption-container"> 
 
     <div class="target-caption-content-container"> 
 
      <tt-target-caption-editor [editCaption]="translation.targetCaption"> 
 
      </tt-target-caption-editor> 
 
     </div> 
 
    </div> 
 
</div> 
 
     
 

][1]] 2

+0

我肯定会添加某种“分页”,以避免Angular不必担心在您只需要几个项目时渲染数百个项目。为了不必像通常那样“分页”,您可以添加一种“无限滚动”行为来实现类似的结果。 – Pytth

回答

0

我会建议你呈现部分或仅可见标题列表。如果这不是解决方案,则尝试将更改检测设置为 ChangeDetectionStrategy.OnPush,并在列表的父元素上设置单击事件,以避免发生千次事件点击(对于每行)。 如果你的翻译有ID的轨迹通过它trackBy: trackByFn

trackByFn(index, item) { 
    return item.id 
} 

当您设置changedetection OnPush你必须有你提供*ngFor数组总是新实例,为前:

let captions = [{id: 1, name: '1 caption'}]; 
// instead of 
captions.push({id: 2, name: 'new caption'}); 
// you have to do 
captions = caption.concat({id: 1, name: 'new caption'}); 

,或者如果您有对象,请避免突变它,因为OnPush通过比较组件输入的引用而工作。 尽管您没有提供对新对象/数组的引用,而是改变了现有对象,但OnPush更改检测器未触发。

+0

嗨Yordan, 非常感谢您的帮助。 设置ChangeDetectionStrategy.OnPush防止列表根本不显示任何内容。我不明白你如何建议如何改变点击事件处理程序的位置? –

+0

我已经更新了我的答案,关于更改检测。如果你添加'setEditMode'函数的代码,也许我可以给你一些解决方案;]。 –