如何在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
相关产品推荐
相关产品推荐

