在Ionic应用程序中处理Toast通知的正确方式

4
我是一名有用的助手,可以为您翻译文本。

我有一个Ionic 2应用程序,在各个位置都有toast通知。

一个很好的例子是当用户在应用程序上更新其个人资料并运行一些验证检查时。如果用户未通过某些验证,我可能会调用以下内容:

      let toast = this.toastCtrl.create({
        message: 'Sorry, your password must be at least 6 characters long.  Your account was not updated.',
        duration: 3000,
        position: 'top'
      });
      toast.present();

没有问题。它只会显示3秒钟然后消失。 当同时显示多个时,问题就出现了。例如,用户可能输入了一个6位字符的密码,但由于其他原因未通过验证,因此另一个 toast 通知被触发:
    let toast = this.toastCtrl.create({
      message: 'Sorry, your passwords do not match.  Your account was not updated.',
      duration: 3000,
      position: 'top'
    });
    toast.present();

这会导致两个提示重叠,其中一个将永久存在。 两个重叠不是问题,但一个无限期存在是一个巨大的问题。
我想这是因为每次都在有效地覆盖“toast”变量。
最好的方法是什么? 我不想有“toast1”,“toast2”等,因为这不会解决问题,因为用户可能会两次启动相同的提示通知(<6字符密码,提交两次)。

你是如何创建Toast的?我同时创建了多个Toast,它们都按预期工作。 - Duannx
1
只需要大量的 let toast = this.toastCtrl.create({ ... }); toast.present();。我只在实验室测试过(ionic serve --lab),但是假设在设备上也是一样的。 - Mike
请查看此答案。通过使用相同的属性,您可以每次只显示一个toast(因为如果它们是验证消息,重叠toast是没有意义的)。 - sebaferreras
@sebaferreras:您知道如何重现这个问题吗?我尝试了很多方法,但是却无法面对它。哈哈 - Duannx
2个回答

8
我建议将所有 Toast 交互处理放在一个服务中。并将其注入到您需要的任何组件/页面/服务中。在服务中,您保留对单个 Toast 的引用,在呈现它之前调用 dismiss()
这个解决方案将防止同时出现多个 Toast。

Toast服务:

import { Injectable } from '@angular/core';
import { ToastController, Toast } from 'ionic-angular';

@Injectable()
export class ToastService{
    toast: Toast = null;

    constructor(private toastCtrl: ToastController){ }

    presentToast(text:string):void{
        let toastData = {
            message: text,
            duration: 3000,
            position: 'top'
        }

        this.showToast(toastData);
    }

    presentClosableToast(text:string):void{
        let toastData = {
            message: text,
            showCloseButton: true,
            closeButtonText: 'X',
            position: 'top' 
        };

        this.showToast(toastData);
    }

    private showToast(data:any):void{
        this.toast ? this.toast.dismiss() : false;
        this.toast = this.toastCtrl.create(data);
        this.toast.present();
    }
}

2
我必须说,我不确定这是否是一个好的方法,因为提供程序不应该直接用于与最终用户(或UI)进行交互。更好的方法是创建一个带有该代码的“BaseComponent”,并将其扩展到您的页面上。或者,如果您只在单个页面中使用toasts,请将此代码添加到该页面中。 - sebaferreras
2
我同意 @sebaferreras。在这种情况下,扩展 classcomponent 之间有区别吗?昨天我进行了编辑(请参见编辑历史记录),我扩展了一个 class。由于只需要功能而不需要模板,所以我使用了 class - robbannn
主要的区别在于 组件 还有元数据(装饰器),虽然在这个例子中元数据并不重要,但是在构建生产环境时可能会导致一些错误(仅在某些版本的Ionic中发生),因此您可以添加一个 空装饰器 来避免这种情况。请参阅此SO答案,其中我创建了一个 BaseComponent 来处理显示/创建提示 :) - sebaferreras

0

你可以像这样做。

当你需要显示一个toast时,调用一个函数。 在函数内部,你有一个3秒的计时器。 然后如果toast函数再次被调用。你需要清除计时器,然后重新设置它。就像这段代码一样。

//delacare timer
_timer:any = null;

showToast(){
    let toast:any;
    //check if timer is running ,if its clear out and dismiss existing toast  
    if (this._timer) { 
         toast.dismiss()
         clearTimeout(this._timer)
    };

    this._timer = setTimeout(() => {
       toast = this.toastCtrl.create({
        message: 'Sorry, your passwords do not match.  Your account was not updated.', 
       position: 'top'
    });
    toast.present();
    },3000)

}

更新

或者你也可以像这样传递一个字符串参数,以避免过多的提示代码。

showToast(string_message){
        let toast:any;
        //check if timer is running it its . clear out  
        if (this._timer) { 
             toast.dismiss()
             clearTimeout(this._timer)
        };

        this._timer = setTimeout(() => {
           toast = this.toastCtrl.create({
            message: string_message, 
           position: 'top'
        });
        toast.present();
        },3000)

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接