使用 Ionic v2 离开页面(向后导航)之前发出警报

Posted

技术标签:

【中文标题】使用 Ionic v2 离开页面(向后导航)之前发出警报【英文标题】:Alert before leaving page (navigate back) with Ionic v2 【发布时间】:2016-10-23 15:11:29 【问题描述】:

如何显示alert,用户必须关闭才能返回上一页?我使用的是标准的<ion-navbar *navbar> 箭头按钮

我尝试像这样挂钩NavController 事件ionViewWillLeave,但它不起作用:

ionViewWillLeave() 
  let alert = Alert.create(
    title: 'Bye',
    subTitle: 'Now leaving',
    buttons: ['OK']
  );
  this.nav.present(alert);

这会显示警报,但一旦关闭就不会返回。如果我将其注释掉,则返回按钮可以正常工作。

【问题讨论】:

【参考方案1】:

这是我的 Bostjan 答案版本,没有抛出未处理的异常。

ionViewCanLeave(): Promise<boolean> 
    return new Promise(resolve => 
        if (!this.formGroup.dirty) return resolve(true);

        this._alertCtrl.create(
            title: 'Confirm leaving',
            message: 'There is unsave work, do you like to continue leaving?',
            buttons: [
                text: 'Leave',
                handler: () => 
                    resolve(true);
                
            , 
                text: 'Stay',
                handler: () => 
                    resolve(false);
                
            ]
        ).present();
    );

【讨论】:

【参考方案2】:

更新

从 Ionic2 RC 开始,现在我们可以使用 Nav Guards。

在某些情况下,开发人员应该能够控制视图离开和 进入。为此,NavController 具有 ionViewCanEnter 和 ionViewCanLeave 方法。类似于 Angular 2 路由守卫,但 与 NavController 更集成

所以现在我们可以这样做:

someMethod(): void 
    // ...
    this.showAlertMessage = true;


ionViewCanLeave() 
    if(this.showAlertMessage) 
        let alertPopup = this.alertCtrl.create(
            title: 'Exit',
            message: '¿Are you sure?',
            buttons: [
                    text: 'Exit',
                    handler: () => 
                        alertPopup.dismiss().then(() => 
                            this.exitPage();
                        );         
                    
                ,
                
                    text: 'Stay',
                    handler: () => 
                        // need to do something if the user stays?
                    
                ]
        );

        // Show the alert
        alertPopup.present();

        // Return false to avoid the page to be popped up
        return false;
    


private exitPage() 
    this.showAlertMessage = false;
    this.navCtrl.pop();

我更喜欢使用this.showAlertMessage 属性,这样当用户尝试退出页面时,我们可以更好地控制何时需要显示警报。例如,我们可能在页面中有一个表单,如果用户没有进行任何更改,我们不想显示警报 (this.showAlertMessage = false),如果表单实际上已更改,我们希望显示警告(this.showAlertMessage = true


老答案

经过几个小时的努力,我找到了解决方案。

我不得不面对的一个问题是ionViewWillLeave 也会在alert 关闭时执行,这使得事情变得更加复杂(当view 即将关闭时,因为您按下了返回按钮, alert 出现,但是当您单击 ok 时,会再次触发事件并再次打开 alert,依此类推...)。

要记住的另一件事是ActionSheetsAlerts 被添加到navigation stack,所以this.nav.pop() 不是从堆栈中删除当前视图,而是删除alert(正因为如此我们可能会觉得它工作不正常)。

话虽如此,我找到的解决方案是:

import Component from '@angular/core';
import NavController, NavParams, Alert from 'ionic-angular';

@Component(
    templateUrl: 'build/pages/mypage/mypage.html',
)
export class MyPage

    // ....

    confirmedExit: boolean = false;

    constructor(private nav: NavController, navParams: NavParams) 
        // ...
    

    ionViewWillLeave() 
        if(!this.confirmedExit) 
            let confirm = Alert.create(
                title: 'Bye',
                message: 'Now leaving',
                buttons: [
                
                    text: 'Ok',
                    handler: () => 
                        this.exitPage();
                    
                
                ]
            );
            this.nav.present(confirm);
        
    

    public exitPage()
        this.confirmedExit = true;
        this.nav.remove().then(() => 
            this.nav.pop();
        );
    


  

所以:

我使用confirmedExit 变量来了解您是否已单击“确定”按钮(因此您确认要退出页面,并且我知道下次触发ionViewWillLeave 事件时,我不会'不必显示alert) 在exitPage 方法中,首先我执行this.nav.remove() 以从堆栈中删除alert,完成后,我们执行this.nav.pop() 以返回上一页。

【讨论】:

添加自定义后退按钮并隐藏自动后退按钮不是更容易吗? @BoštjanPišler 但是如果用户不使用那个新按钮,而是使用 android 物理后退按钮怎么办? 啊啊,触摸 :) 我实际上在让这个在 RC3 中工作时遇到问题,页面导航然后出现警报。有什么想法吗? 是的,刚刚发布了与新答案相同的内容:)【参考方案3】:

已接受的解决方案在 RC3 中不起作用,这是使用 Nav Controller 的 Nav Guard 的新解决方案:

ionViewCanLeave(): Promise<void> 
  return new Promise((resolve, reject) => 
    let confirm = this.alertCtrl.create(
      title: 'Are you sure?',
      message: 'Bunnies will die :(',
      buttons: [
        text: 'OK',
        handler: () => 
          resolve();
        ,
      , 
        text: 'Cancel',
        handler: () => 
          reject();
        
      ],
    );
    confirm.present();
  )

如果您在导航控制器上使用 push() 进行导航,您还需要对其进行捕捉,否则会引发未处理的错误:

this.navCtrl.push(SomePage).catch(() => );

【讨论】:

我刚试过这个(RC3,最新的应用程序脚本),但是当 'OK' 工作时,'Cancel' 抛出:.\node_modules\@angular\core\src\error_handler.js:53 Error: Uncaught (in promise): false 你说得对,在使用 push 或类似的情况下必须使用 catch,我编辑了答案,谢谢。 这应该是公认的答案。 @Cocowalla ,隐式错误处理将添加到 v2.1.0 使用 2.1.0,将返回类型更改为 Promise 否则会出现类型不匹配错误。除此之外,这是一种享受,干杯! 谢谢,这是一个公认的答案。它对我有用。

以上是关于使用 Ionic v2 离开页面(向后导航)之前发出警报的主要内容,如果未能解决你的问题,请参考以下文章

ionic怎样在页面离开后清楚缓存

带有 ionic-2-sidemenu 应用程序的顶部导航栏中的导航按钮

ionic痛点:Android真机物理返回按钮问题!GitHub问题归纳

Ionic HTML5 混合APP开发框架-创建新页面和导航

如何在 Ionic 4 中添加标签动画?

如何在Ionic 2应用程序中提取和重用导航栏模板和逻辑?