You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ionic Angular中实现CanDeactivateFn守卫?求示例

Ionic Angular 新版 CanDeactivateFn 守卫实现示例

1. 定义组件退出确认接口

先创建一个接口,让需要启用退出守卫的组件实现它:

// src/app/guards/can-component-deactivate.ts
import { Observable } from 'rxjs';

export interface CanComponentDeactivate {
  canDeactivate: () => boolean | Observable<boolean> | Promise<boolean>;
}

2. 创建 CanDeactivateFn 守卫函数

Angular 14+ 采用函数式守卫,无需创建类,直接编写守卫逻辑:

// src/app/guards/unsaved-changes.guard.ts
import { CanDeactivateFn } from '@angular/router';
import { CanComponentDeactivate } from './can-component-deactivate';
import { inject } from '@angular/core';
import { AlertController } from '@ionic/angular';

export const unsavedChangesGuard: CanDeactivateFn<CanComponentDeactivate> = (component) => {
  // 注入Ionic的弹窗控制器
  const alertController = inject(AlertController);

  // 调用组件的判断方法,确认是否需要拦截退出
  const canLeave = component.canDeactivate();

  // 直接返回布尔值的情况
  if (typeof canLeave === 'boolean') {
    return canLeave;
  }

  // 处理异步场景,弹出Ionic确认弹窗
  return new Observable<boolean>(observer => {
    alertController.create({
      header: '确认离开',
      message: '你有未保存的更改,确定要离开吗?',
      buttons: [
        {
          text: '取消',
          role: 'cancel',
          handler: () => {
            observer.next(false);
            observer.complete();
          }
        },
        {
          text: '确定离开',
          handler: () => {
            observer.next(true);
            observer.complete();
          }
        }
      ]
    }).then(alert => alert.present());
  });
};

3. 在组件中实现退出判断逻辑

以表单组件为例,判断是否存在未保存的修改:

// src/app/pages/form/form.page.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { CanComponentDeactivate } from '../../guards/can-component-deactivate';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-form',
  templateUrl: './form.page.html',
  styleUrls: ['./form.page.scss'],
})
export class FormPage implements OnInit, CanComponentDeactivate {
  form: FormGroup;
  originalFormValue: any;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      name: [''],
      email: ['']
    });
  }

  ngOnInit() {
    // 保存表单初始值,用于对比是否有修改
    this.originalFormValue = this.form.value;
  }

  canDeactivate(): boolean | Observable<boolean> {
    // 判断表单内容是否发生变化
    const hasUnsavedChanges = JSON.stringify(this.form.value) !== JSON.stringify(this.originalFormValue);
    
    // 没有修改直接允许离开,有修改则返回Observable交给守卫处理弹窗
    return hasUnsavedChanges ? new Observable(observer => {
      observer.next(false);
      observer.complete();
    }) : true;
  }
}

4. 在路由配置中应用守卫

给需要拦截退出的路由添加canDeactivate配置:

// src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
import { unsavedChangesGuard } from './guards/unsaved-changes.guard';

const routes: Routes = [
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full'
  },
  {
    path: 'form',
    loadChildren: () => import('./pages/form/form.module').then(m => m.FormPageModule),
    canDeactivate: [unsavedChangesGuard] // 启用退出守卫
  },
  // 其他路由配置...
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

核心说明

  • 函数式CanDeactivateFn无需继承类,直接通过inject()注入所需服务
  • 组件必须实现CanComponentDeactivate接口,确保守卫能调用组件的判断逻辑
  • 统一在守卫中处理弹窗逻辑,避免组件代码冗余,也方便全局复用守卫规则

内容的提问来源于stack exchange,提问作者KTSB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 01:02:26