为什么 Angular 组件在点击后才更新?

Why Angular component is just updating after click?

我是 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:我不局限于任何特定的实现,所以如果需要我可以改变方法。

在您的 NotificationComponent class 中,将 ChangeDetectorRef 注入 constructor 并显式更新 messages 数组,以便 angular 可以推断出 属性 已更改,因此更新 UI

  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();
      }
    });
  }