2016-09-17 16 views
1

我有一個包含用戶操作的歷史流的應用程序。歷史會顯示幾天或整週。在一天內大約有大約400-2k的事件要顯示。Angular2中長列表呈現效果不佳

可能發生的操作類型很少,每個操作的顯示方式都不相同(例如註釋或對象修改)。因此每個循環迭代中都有一些邏輯來確定每個元素的最終結構。

問題是,它需要大量的渲染時間,約1300個元素渲染大約6秒。對我來說,等待這樣的事情是相當長的時間。我試圖優化代碼來完成所需的最小代碼,但仍然可以獲得的最好結果是1300個元素的6秒。

另一個更大的問題是在渲染過程中凍結瀏覽器,這是很長時間內不可接受的。

我不確定自己是否做錯了什麼,或者我找到了Angular2的一週無法解決的問題。所以任何暗示都是值得歡迎的。 我對這樣的建議不感興趣:使用分頁或使用無限滾動,我正在尋找一種方法,使其工作更快,並扼殺。

我還會補充說,以前在服務器端渲染歷史記錄並將結果放入DOM的過程非常快,無論事件的數量如何。進一步的截圖也表明,真正的渲染時間只是這個過程中很小的一部分。

我已經準備在plunker渲染代碼的簡化版本,其示出了該問題: http://plnkr.co/edit/QrYmYezmlV3MkQV5bOA8?p=preview

主要渲染部分:

根ngFor元件

<div class="history-stream"> 
    <div *ngFor="let action of history" 
     class="activity" [ngClass]="{'first-of-user': action.firstOfUser, 'last-of-user': action.lastOfUser}"> 
    <p class="date" *ngIf="action.firstOfDay">{{ action.date | date:'mediumDate' }}</p> 
    <div class="user-entry" [ngSwitch]="action.type"> 
     <comment *ngSwitchCase="'comment'" [object]="action"></comment> 
     <modified *ngSwitchCase="'modified'" [object]="action"></modified> 
    </div> 
    </div> 
</div> 

註釋組件:

<div class="entry comment" [ngClass]="{'comment-resolved': object.extra.is_resolved}"> 
    <a href="{{ getDeleteUrl(object.extra.comment_id) }}" data-target="metabase-modal-ajax" class="comment-action">Delete</a> 
    <a href="#" class="comment-action" *ngIf="!object.extra.is_resolved" (click)="resolveComment($event)">Mark as resolved</a> 
    <a href="#" class="comment-action" *ngIf="object.extra.is_resolved" (click)="unResolveComment($event)">Unresolve</a> 
    <p class="action" [innerHTML]="object.action"></p> 
    <p>{{ object.comment }}</p> 
    <small class="text-muted">{{ object.date | date:'shortTime' }} <span class="dot">&middot;</span> {{ object.date | date:'shortTime' }}</small> 
</div> 

修改的事件組成:

<div class="entry modified"> 
    <p class="action" [innerHTML]="object.action"></p> 
    <ul class="changes list-unstyled"> 
    <li *ngFor="let change of object.changes"> 
     <span class="attribute">{{ change.attribute }}:</span>&nbsp; 
     <modified-value [change]="change.from"></modified-value> 
     <span class="arrow">&rarr;</span>&nbsp; 
     <modified-value [change]="change.to"></modified-value> 
     <small class="time text-muted">{{ change.date | date:'shortTime' }} <span class="dot">&middot;</span> {{ change.date | date:'shortTime' }}</small> 
    </li> 
    </ul> 
</div> 

和改良价值成分:

<span [ngSwitch]="getChangeType()"> 
    <span *ngSwitchCase="'complex'"> 
    <span *ngFor="let item of change"> 
     <span class="badge">{{ item.tag }}</span> 
     <span [ngSwitch]="isArray(item.value)"> 
     <span *ngSwitchCase="true"> 
      <span *ngFor="let valueItem of item.value" class="value tag">{{ valueItem }}</span> 
      <span *ngIf="isEmpty(item.value)" class="value text-muted">None</span> 
     </span> 
     <span *ngSwitchCase="false"> 
      <span *ngIf="item.value" class="value">{{ item.value }}</span> 
      <span *ngIf="!item.value" class="value text-muted">None</span> 
     </span> 
     </span> 
    </span> 
    </span> 
    <span *ngSwitchDefault> 
    <span *ngIf="change" class="value">{{ change }}</span> 
    <span *ngIf="!change" class="value text-muted">None</span> 
    </span> 
</span> 

而且配置文件記錄的幾張截圖:

enter image description here

enter image description here

+0

角度適合小項目和初學者。對於較大的一個,只有純JavaScript是這樣的(在這種情況下快3倍) – cpugourou

+0

我同意角度會帶來額外的開銷,但是它背後有一個更大的圖景(爲簡單起見,這是從示例中刪除的) 。因爲歷史流是交互式的,具有許多複雜的過濾選項等等。所有這些都很容易用角度來實現,在純js中,我將不得不自己實現大量的東西。 –

+0

我刪除了我的答案,因爲它不符合你的需求,如果還有其他的東西出現在我的腦海裏,我會再給它一次:) – MatWaligora

回答

1

日期格式了一半的腳本時間在你的例子中。

看到這裏http://plnkr.co/edit/ChqgowTWjOailPFcLs34?p=preview沒有日期,並利用一些修改

3.6s - scripting 
1.4s - rendering 

相當大的價值。我認爲增量渲染和觀察值在這裏很有用