首页 > 解决方案 > 为什么 Angular 组件在点击后才更新?

问题描述

我是 Angular 的新手,所以我不会对我缺少基本的东西感到惊讶。我尝试了 Angular 文档和谷歌搜索,但目前还不知道为什么我的组件在单击后才更新 UI?

我的场景是,我想要一个名为 NotificationComponent 的共享组件和一个名为NotificationService共享服务。由于我可能会发生 1 个以上的错误,因此我的NotificationComponent应该显示所有这些消息。最重要的是,我有一个 http 错误拦截器和一个自定义错误处理。

发生的事情是,我收到 3 个 https 错误,拦截器收到所有 3 个错误,自定义错误处理正在处理所有 3 个错误,通知服务正在创建所有 3 个错误,但通知组件仅自动呈现 1 个(有时是 2 个)错误。一旦我单击 UI 中的任意位置,就会显示提醒消息。为什么会这样?

层次结构:AppModule导入SharedModule[包含通知服务和组件]。通知组件选择器在里面app.component.html

零件:

@Component({
  selector: 'app-notification',
  templateUrl: './notification.component.html',
  styleUrls: ['./notification.component.scss']
})
export class NotificationComponent implements OnInit, OnDestroy  {
  
  messages: Message[] = [];
  notificationSubscription: Subscription;

  constructor(private notificationService: NotificationService) { }

  ngOnInit() {
    this.notificationSubscription = this.notificationService.onNotify()
      .subscribe(msg => {
        this.messages.push(msg);
      });
  }

  ngOnDestroy() {
    // unsubscribe to avoid memory leaks
    this.notificationSubscription.unsubscribe();
  }
}

HTML:

<div *ngFor = "let msg of messages" role="alert">
    {{msg.detail}}
</div>

服务:

@Injectable({
  providedIn: 'root'
})

export class NotificationService {

    messages: Message[];
    private subject = new Subject<Message>();

    constructor() {
        this.messages = [];
    }

    onNotify(): Observable<Message> {
      return this.subject.asObservable();
    }
  
    error(title: string, detail: string): void {
      this.notify({type: 'error', title: title, detail: detail});
    }

    notify(message: Message) {
      this.subject.next(message);
    }
}

自定义错误处理程序:

@Injectable()
export class CustomErrorHandler implements ErrorHandler {

    constructor(@Inject(NotificationService) 
        private notificationService: NotificationService) {
    }

    handleError(error: any): void {
        
        this.notificationService.error(error.title, error.detail);
    }

}

PS:我不限于任何特定的实现,所以如果需要我可以改变方法。

标签: angularangular-componentsangular-observable

解决方案


在您的课程中NotificationComponent,注入并显式更新数组,以便 Angular 可以推断该属性已更改并因此更新 UIChangeDetectorRefconstructormessages

  constructor(
    private readonly changeDetector: ChangeDetectorRef,
    private readonly notificationService: NotificationService
  ) {}

  public ngOnInit(): void {
    this.notificationSubscription = this.notificationService
      .onNotify()
      .subscribe({
        next: (msg) => {
        // Don't mutate existing array, Angular can't infer if it should update UI
        this.messages = [...this.messages, msg];
        // explicitly update UI if the above approach doesn't work
        this.changeDetector.detectChanges();
      }
    });
  }

推荐阅读