简体   繁体   English

如何在 Angular 中使用 *ngFor 提高渲染性能

[英]How to improve rendering performance with *ngFor in Angular

I am creating a chat app, and performance is slow when a lot of messages are sent at once.我正在创建一个聊天应用程序,当一次发送大量消息时性能很慢。 The messages show up but the UI becomes unresponsive for a while.消息显示,但 UI 有一段时间没有响应。 Here is a simplified version of the code and how can I fix this?这是代码的简化版本,我该如何解决?

HTML: HTML:

<div class="message-notification" *ngFor="let newMessage of chatMessages"; trackBy: trackByMsgs>
   <custom-notification [incomingChat]="newMessage" (dismissedEvent)="onDismiss($event)" (closedEvent)="onNotifcationClose($event)"></custom-notification>
</div>

TS: TS:

newChatMessages: any[];

constructor(private chatService: ChatService) {}

 ngOnInit() {
    this.chatService.chatMsg.subscribe((msg:any) => {
    if (msg) {
       this.activatePopup(msg);
    }
  }

  activatePopup(message) {
    if (message.msgId !== null && message.title !== null) {
       this.setTitle(message);

    //If popup is already open then do not display a duplicate popup for the same message
         let index = this.isPopupOpen(message);
         if (index === -1) {
           newChatMessages.push(message);
         }else {
           newChatMessages[index] = message;
         }
     }
  }

   trackByMsgs(index:number, msg:any) {
     return msg.msgId && msg.title;
   }

   isPopUpOpen(message){
     let index = -1;
     if (this.newChatMessages){
      index = this.newChatMessages.findIndex(
         msg => msg.id === message.id && msg.title === message.title);
      }
    return index;
   }

In order to help you, can you provide a reproduction in Stackblitz please?为了帮助你,你能在 Stackblitz 中提供一个复制品吗?

The best in your case is to control the angular change detection manually by using OnPush Change Detection Strategy .在您的情况下,最好的方法是使用OnPush Change Detection Strategy手动控制 angular 更改检测。 You should carefully use it, cause when it's on, angular will detect changes only if onChanges lifecycle is been triggered or async pipe has received a new value.您应该小心使用它,因为当它打开时,angular 只有在触发 onChanges 生命周期或异步 pipe 收到新值时才会检测到更改。 It also applies to all the component children.它也适用于所有子组件。

Then you would need to detect the changes manually by injecting the ChangeDetectorRef in your component and call the method detectChanges on it each time you want to apply your data changes to your dom.然后,您需要通过在组件中注入ChangeDetectorRef来手动检测更改,并在每次要将数据更改应用于 dom 时对其调用方法 detectChanges。
Read this article for better understanding阅读这篇文章以获得更好的理解

Another interesting article for improving the performance of your angular app https://medium.com/swlh/angular-performance-optimization-techniques-5b7ca0808f8b另一篇关于提高 angular 应用程序性能的有趣文章https://medium.com/swlh/angular-performance-optimization-techniques-5b7ca0808f8b

Using trackBy helps angular to memorize the loaded elements in the ngFor and update only the changed once on change detection.使用 trackBy 有助于 angular 记住 ngFor 中加载的元素,并在更改检测时仅更新更改的一次。 But your trackByMsgs returns a boolean which is not what it should return.但是您的trackByMsgs返回一个 boolean 这不是它应该返回的。 If you adjust your trackBy to return a unique key like msg.msgId or the index of the item, you might see a difference.如果您调整 trackBy 以返回唯一键,例如 msg.msgId 或项目的索引,您可能会看到差异。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM