Angular中通过复用代码检测所有编辑页面未保存变更并提示用户
全局检测未保存变更的Angular实现方案
需求与现状
需要在所有页面检测用户未保存的表单变更,当用户点击返回按钮或刷新页面时弹出提示。当前已在单个页面通过canDeactivate守卫实现该功能,但希望通过Directive复用逻辑,避免重复代码。
当前单页实现代码:
@HostListener('window:beforeunload') canDeactivate(): boolean | Observable<boolean> { return !this.NameFormControl.dirty; }
基于Directive的全局复用方案
1. 创建通用检测Directive
封装表单变更检测逻辑,监听表单dirty状态,并处理页面刷新的beforeunload事件:
import { Directive, Input, HostListener } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; @Directive({ selector: '[appUnsavedChanges]' }) export class UnsavedChangesDirective { @Input('appUnsavedChanges') form: FormGroup | FormControl; @HostListener('window:beforeunload', ['$event']) handleBeforeUnload(event: Event): void { if (this.form.dirty) { event.preventDefault(); // 适配部分浏览器的提示触发逻辑 event.returnValue = ''; } } hasUnsavedChanges(): boolean | Observable<boolean> { return this.form.dirty ? confirm('您有未保存的变更,确定要离开吗?') : true; } }
2. 实现全局可复用的CanDeactivate守卫
让守卫检测组件是否应用了上述Directive,调用其检测方法:
import { CanDeactivate } from '@angular/router'; import { Injectable } from '@angular/core'; import { UnsavedChangesDirective } from './unsaved-changes.directive'; export interface CanComponentDeactivate { hasUnsavedChanges(): boolean | Observable<boolean>; } @Injectable({ providedIn: 'root' }) export class UnsavedChangesGuard implements CanDeactivate<CanComponentDeactivate | UnsavedChangesDirective> { canDeactivate(component: CanComponentDeactivate | UnsavedChangesDirective): boolean | Observable<boolean> { // 优先调用组件自身的检测方法,否则使用Directive的逻辑 if ('hasUnsavedChanges' in component) { return component.hasUnsavedChanges(); } return true; } }
3. 在组件和路由中应用
- 在需要检测的组件模板中绑定Directive:
<form [formGroup]="myForm" appUnsavedChanges [appUnsavedChanges]="myForm"> <!-- 表单内容 --> </form>
- 在路由配置中全局应用守卫(父路由设置后,子路由自动继承):
const routes: Routes = [ { path: '', canDeactivate: [UnsavedChangesGuard], children: [ { path: 'page1', component: Page1Component }, { path: 'page2', component: Page2Component } // 其他需要检测的页面路由 ] } ];
补充说明
- 若组件使用独立
FormControl而非FormGroup,直接绑定对应的FormControl即可 - 部分页面需自定义提示逻辑时,可让组件实现
CanComponentDeactivate接口,重写hasUnsavedChanges方法,守卫会优先调用组件自身逻辑
内容的提问来源于stack exchange,提问作者Mukesh
相关产品推荐
相关产品推荐

