如何将页面添加到导航历史记录以防止应用程序退出?

How to add a page to navigation history to prevent app from exiting?

我对 Ionic 4 还是比较陌生。我正在制作一个接收推送通知的应用程序。应用内的导航是这样的:

Home page -> Detail page 

每次用户点击通知时,应用都会打开并导航到详细信息页面。导航有效,但由于导航历史为空,如果用户点击硬件后退按钮,应用程序将退出。我希望它将用户重定向到主页。

如何在 Ionic 4 中实现这一点?有没有办法将页面推送到导航历史记录?我已阅读文档,但找不到任何相关信息。最接近的可能是 NavCtrl.push() 但它在 Ionic 4 中不再可用。

谢谢。

可能有一种更简单的方法可以做到这一点,但以下方法非常灵活,因为当用户想要从显示的页面返回时,它允许您 运行 任何自定义逻辑推送通知或深度 link 已打开。

请看this StackBlitz demo.

请注意,在演示中,由于 app-routing.module 文件中的以下代码,我会在应用程序加载后立即重定向到 DetailsPage

{
  path: "",
  redirectTo: "/details/1?fromDeepLink=true", // <-- here!
  pathMatch: "full"
}

无论如何,重要的部分发生在 DetailsPage。在那里,您需要处理当用户尝试使用 a) 来自 header 的后退按钮和 b) 来自 Android 设备

的物理后退按钮时发生的情况

代码很漂亮 self-explanatory,但基本上在那个页面我正在寻找 fromDeepLink 查询字符串参数,如果是 true,应用程序将注册一个自定义header 设备的后退按钮和 Android 设备的物理后退按钮的操作。

自定义操作将 HomePage 设置为根页面,但将 animationDirection 参数设置为 'back'。这样一来,即使我们实际上将其添加到导航堆栈,用户也会返回到该页面。

请务必注意,一旦用户离开页面,此自定义处理程序就会被删除,这样我们就不会影响任何其他页面中后退按钮的默认行为。

import { Component, OnInit, ViewChild } from "@angular/core";
import { ActivatedRoute } from "@angular/router";

import { IonBackButtonDelegate, NavController,  Platform,  ViewDidEnter, ViewWillLeave } from "@ionic/angular";

import { Subscription } from "rxjs";

@Component({
  selector: "app-details",
  templateUrl: "./details.page.html",
  styleUrls: ["./details.page.scss"]
})
export class DetailsPage implements OnInit, ViewDidEnter, ViewWillLeave {
  @ViewChild(IonBackButtonDelegate, { static: false })
  public backButton: IonBackButtonDelegate;

  public itemId: number;
  public fromDeepLink: boolean = false;

  private unregisterBackButtonAction: Subscription;

  constructor(
    private platform: Platform,
    private route: ActivatedRoute, 
    private navCtrl: NavController,
  ) {}

  ngOnInit() {
    const itemIdParam = this.route.snapshot.paramMap.get("itemId");
    const fromDeepLinkParam = this.route.snapshot.queryParamMap.get('fromDeepLink');

    this.itemId = +itemIdParam;
    this.fromDeepLink = fromDeepLinkParam 
      ? fromDeepLinkParam.toLocaleLowerCase() === 'true' 
      : false;
  }

  ionViewDidEnter() {
    if(this.fromDeepLink) {
      this.initializeCustomBackButtonAction()
    }
  }

  ionViewWillLeave() {
    if(this.fromDeepLink) {
      this.removeCustomBackButtonAction();
    }
  }

  private initializeCustomBackButtonAction(): void {
    const leavingCallback = () => {
      console.log('Using custom back button action');
      this.navCtrl.navigateRoot('/home', { animationDirection: 'back' });
    };

    // Override the back button from the header
    if (this.backButton) {
      this.backButton.onClick = leavingCallback;
    }

    // Override the physical back button from Android devices
    this.unregisterBackButtonAction = this.platform.backButton.subscribeWithPriority(10, leavingCallback);
  }

  private removeCustomBackButtonAction(): void {
    this.unregisterBackButtonAction?.unsubscribe();
  }
}

另请注意,如果导航堆栈中当前页面之前没有页面,默认情况下 ion-back-button 不会显示,因此在演示中我设置 defaultHref 属性 像这样:

<ion-back-button defaultHref></ion-back-button>

我将其留空,因为该组件实际上将覆盖此后退按钮对我的自定义后退按钮操作的作用。但需要在模板中添加defaultHref,否则后退按钮不会显示。