首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Angular8 trackby未正确更新

Angular8 trackby未正确更新
EN

Stack Overflow用户
提问于 2019-09-01 02:00:59
回答 1查看 1.2K关注 0票数 0

因此,首先来介绍一下背景知识。我正在开发一个应用程序,正在使用agm地图来实时显示多个用户的位置。我最近一直在努力提高性能,因为可能有数千个用户,每个用户代表一个地图标记或dom元素。我已经将父组件和子组件更改为同时使用onpush策略,子组件使用ngFor循环呈现地图标记,我还将trackBy添加到此循环中。通过signalr接收位置更新,对象被正确更新,但即使在运行更改检测之后,标记在地图上的位置也没有被正确更新。

下面的两个组件是为了帮助识别问题而简化的版本。

首先是父Map组件

代码语言:javascript
复制
     @Component({
      selector: 'app-map',
      template: '<agm-map>
                    <app-map-markers #mapMarkers [users]="users"></app-map-markers>
                </agm-map>',
      changeDetection: ChangeDetectionStrategy.OnPush
    })
    export class MapComponent implements OnInit, OnDestroy {
        users: MapUser[];

        private handleLocationUpdate(updatedUser: any) {
           const user = this.users.find(this.findIndexToUpdate, updatedUser.Id);

           if (user !== null && user !== undefined) {
              user.lat = updatedUser.Lat;
              user.lng = updatedUser.Lng;
              user.lastSeen = updatedUser.LastSeen;

              const userIndex = this.handledUsers.indexOf(user);
              this.handledUsers[userIndex] = user;
           }
        }

        findIndexToUpdate(newItem) {
           return newItem.id === this;
        }
    }

用户数组是通过对http服务的继承来填充的,但我省略了这一点,因为它工作得很好。当接收到位置更新时,它由父级处理,我离开了函数来显示这一点,但再次通过订阅signalr服务来调用该函数。

现在是地图标记组件。

代码语言:javascript
复制
 @Component({
  selector: 'app-map-markers',
  template: '<agm-marker *ngFor="let user of users; let i = index; trackBy: trackByUser"  [latitude]="user.lat" [longitude]="user.lng" [title]="user.firstName">
             </agm-marker>',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MapMarkersComponent {
    @Input() users: MapUser[];

    constructor() {}

    public trackByUser(indx: number, value: MapUser) {
        let identifier: string = indx.toString();

        if ('lat' in value && 'lng' in value) {
          identifier = identifier.concat(value.lastSeen.toString());
        }

        return identifier;
      }
}

我怀疑问题是由于onpush没有检测到变化,然而出于性能原因,onpush似乎是这种情况下最好的策略。我只需要更新元素,而不是重新绘制整个用户列表。但也许我对angular还很陌生,所以我把我的电线都弄乱了。感谢您的帮助或建议。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-01 02:26:12

尝试调用更改检测'markForCheck()‘,这将使角度在下一个周期中运行更改检测。

代码语言:javascript
复制
@Component({
  selector: 'app-map-markers',
  template: '<agm-marker *ngFor="let user of users; let i = index; trackBy: trackByUser"  [latitude]="user.lat" [longitude]="user.lng" [title]="user.firstName">
             </agm-marker>',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MapMarkersComponent {
    public users: MapUser[]
    @Input() 
    set users(values: any[]){
      this.users = values;
      this.cdr.markForCheck();
    }

    constructor(private cdr: changeDetectorRef) {}

    public trackByUser(indx: number, value: MapUser) {
        let identifier: string = indx.toString();

        if ('lat' in value && 'lng' in value) {
          identifier = identifier.concat(value.lastSeen.toString());
        }

        return identifier;
      }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57740459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档