为什么 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();
}
});
}
我是 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();
}
});
}