问题
我CanDeactivate
在 Angular 中使用了一个保护机制,用于在用户离开包含未保存更改的表单之前提示用户。对于正常的路由更改(例如,点击链接),它运行良好,但当用户按下浏览器的“后退”按钮时,它就会中断。
设想
假设我的路由流程是:
/主页 → /用户 → /编辑
- 用户
/edit
尚未保存更改。 - 按下浏览器后退按钮。
- 通过 显示确认对话框
CanDeactivate
。 - 如果用户取消,路线保持不变(正确)。
- 但当他们再次按下并确认时,它会跳过两步导航回
/home
。/user
我尝试过
我实施了CanDeactivate
这样的守卫:
export class YourFormComponent implements CanComponentDeactivate, OnInit, AfterViewInit {
hasUnsavedChanges = false;
// Implement the canDeactivate method
canDeactivate(): Observable<boolean> | boolean {
if (!this.hasUnsavedChanges) {
return true;
}
const confirmLeave = window.confirm('You have unsaved changes. Leave anyway?');
return confirmLeave;
}
}
路线.ts
import { Routes } from '@angular/router';
import { YourFormComponent } from './your-form.component';
import { ConfirmLeaveGuard } from './confirm-leave.guard';
const routes: Routes = [
{
path: 'form',
component: YourFormComponent,
canDeactivate: [ConfirmLeaveGuard]
}
];
确认离开.guard.ts
import { inject } from '@angular/core';
import { CanDeactivateFn } from '@angular/router';
import { Observable } from 'rxjs';
import { Location } from '@angular/common';
export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
export const ConfirmLeaveGuard: CanDeactivateFn<CanComponentDeactivate> = (component: any, currentRoute, currentState, nextState) => {
const location = inject(Location);
const result = component.canDeactivate();
// If it's a boolean value
if (typeof result === 'boolean') {
if (!result) {
location.replaceState(window.location.pathname); // Restore URL
}
return result;
}
// If it's an Observable or Promise
if (result instanceof Observable || result instanceof Promise) {
return new Promise(resolve => {
Promise.resolve(result).then(confirmed => {
if (!confirmed) {
location.replaceState(window.location.pathname); // Restore URL
}
resolve(confirmed);
});
});
}
return true;
};
我还尝试在防护装置内使用 Location.replaceState() 或 Location.go() 来恢复历史记录堆栈,但在使用后退按钮时仍然会出现异常。
问题如何使用 CanDeactivate 正确处理浏览器后退按钮以防止重复导航或跳过路线?
任何建议或例子都将不胜感激。