【发布时间】:2023-03-17 15:01:01
【问题描述】:
我正在使用 Snackbar 向用户显示错误和警告消息。有时这些可能在时间上彼此接近,比第一条消息的显示持续时间更接近。如此接近,以至于用户在用第二条消息覆盖之前没有足够的时间阅读第一条消息。
有没有办法将行为更改为在显示第二条消息之前等待第一条消息结束,或者将它们堆积起来?
【问题讨论】:
标签: angular angular-material angular7
我正在使用 Snackbar 向用户显示错误和警告消息。有时这些可能在时间上彼此接近,比第一条消息的显示持续时间更接近。如此接近,以至于用户在用第二条消息覆盖之前没有足够的时间阅读第一条消息。
有没有办法将行为更改为在显示第二条消息之前等待第一条消息结束,或者将它们堆积起来?
【问题讨论】:
标签: angular angular-material angular7
您可以将所有消息放入一个数组中,以模拟消息的“队列”,而不是为每条消息调用 Snackbar。我建议有一个服务来负责处理这个问题。
然后,在此服务中,您可以订阅 Snackbar 的 afterDismissed() 回调,该回调将在 Snackbar 关闭时触发。下面是一个简单的例子:
messageQueue: string[] = [
'Message 1',
'Message 2',
'Message 3'
]
private displaySnackbar(): void {
const nextMessage = this.getNextMessage();
if(!nextMessage){
return;
}
this.snackBar.open(nextMessage, undefined, { duration: 1000 })
.afterDismissed()
.subscribe(() => {
this.displaySnackbar();
});
}
private getNextMessage(): string | undefined {
return this.messageQueue.length ? this.messageQueue.shift() : undefined;
}
编辑:
为了避免任何混淆,在我提供的示例中,我不建议直接调用displaySnackbar()(因此private 可见范围)。相反,这是我公开它的方式(您可以在下面的 Stackblitz 演示中看到):
addMessage(message: string): void {
this.messageQueue.push(message);
if(!this.processingMessage) {
this.displaySnackbar();
}
}
这仅取决于processingMessage 标志来确定它是否应该调用displaySnackbar() 方法。当然我们还需要设置这个标志,所以这里是更新的displaySnackbar():
private displaySnackbar(): void {
const nextMessage = this.getNextMessage();
if(!nextMessage){
this.processingMessage = false; // No message in the queue, set flag false
return;
}
this.processingMessage = true; // A message was dequeued and is being processed
this.snackBar.open(nextMessage, undefined, { duration: 1000 })
.afterDismissed()
.subscribe(() => {
this.displaySnackbar();
});
}
Here 是基本的、可运行的 Stackblitz 演示。
在演示中,您将看到您可以“垃圾邮件单击”“添加消息”按钮,该按钮会将所有创建的消息排队,但 Snackbar 只会在每条消息完成显示后显示它们1 秒。
【讨论】:
afterDismissed 订阅是一次性可观察的(类似于 http get),因此事后不会留下任何订阅。 “在这种配置中,这不可能……”到底是怎么回事?