我有一個包含用戶操作的歷史流的應用程序。歷史會顯示幾天或整週。在一天內大約有大約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">·</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>
<modified-value [change]="change.from"></modified-value>
<span class="arrow">→</span>
<modified-value [change]="change.to"></modified-value>
<small class="time text-muted">{{ change.date | date:'shortTime' }} <span class="dot">·</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>
而且配置文件記錄的幾張截圖:
角度適合小項目和初學者。對於較大的一個,只有純JavaScript是這樣的(在這種情況下快3倍) – cpugourou
我同意角度會帶來額外的開銷,但是它背後有一個更大的圖景(爲簡單起見,這是從示例中刪除的) 。因爲歷史流是交互式的,具有許多複雜的過濾選項等等。所有這些都很容易用角度來實現,在純js中,我將不得不自己實現大量的東西。 –
我刪除了我的答案,因爲它不符合你的需求,如果還有其他的東西出現在我的腦海裏,我會再給它一次:) – MatWaligora