大約五年前我看到了一個類似的問題,但我的問題有點不同:
我為整個應用程式組件撰寫了一個面包屑,作為我最外層布局的一部分。
在面包屑中,我使用了“location.back()”來制作后退按鈕:
<i
*ngIf="this.urlLevels > 1"
nz-icon
nzType="arrow-left"
nzTheme="outline"
(click)="back()"
></i>
import { Location } from '@angular/common';
constructor(private location: Location) {}
back() {
this.location.back();
}
我的應用程式路線如:
{
path: '',
redirectTo: 'blog',
pathMatch: 'full',
},
{
path: 'login',
component: LoginComponent,
},
{
path: '',
canActivateChild: [RouteGuard],
children: [
{
path: 'blog',
component: LayoutComponent, // breadcrumb is a part of this component
children: [
{
path: '',
loadChildren: () => import('src/app/blog/blog.module').then((m) => m. BlogModule),
},
],
data: {
icon: '',
breadcrumb: 'Blog'
},
},
],
},
{
path: '**',
component: NotFoundComponent,
},
BlogModule 的路由如下:
{ path: '', redirectTo: 'bloglist', pathMatch: 'full' },
{
path: 'bloglist',
component: BlogListComponent,
data: {
breadcrumb: '',
},
},
{
path: 'createblog',
component: CreateBlogComponent,
data: {
breadcrumb: 'CreateBlog',
},
canDeactivate: [BeforeLeaveGuard],
},
BeforeLeaveGuard:
import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs';
import { CreateBlogComponent } from './create-blog.component';
@Injectable()
export class BeforeLeaveGuard implements CanDeactivate< CreateBlogComponent > {
canDeactivate(component: CreateBlogComponent): Observable<boolean> | boolean {
component.openDialog(); // I open a leave-confirm dialog here
return component.confirmed; // result of confirm dialog
}
}
問題是:當我點擊后退按鈕時,我的 CanDeactivate 不起作用,我的頁面發生了變化,就像沒有警衛一樣。
我在http://angular.io/api/router/Router看到了兩種路由方法,分別是:initialNavigation(), setUpLocationChangeListener()
他們似乎可以幫助我解決我的問題。我嘗試在我的 BlogModule 中使用它們,但它們都不起作用(什么也沒發生,我的頁面仍然成功更改,忽略了我的所有設定)。
問題是什么?T_T
我需要你的幫助。
uj5u.com熱心網友回復:
這里發生了一些事情,但是您嘗試做的事情是可能的。
1.等待對話是一個異步操作
在您的 CanDeactivate 代碼中:
canDeactivate(component: CreateBlogComponent): Observable<boolean> | boolean {
component.openDialog(); // I open a leave-confirm dialog here
return component.confirmed; // result of confirm dialog
}
您打開對話框,但在 Javascript(和 Typescript)中等待用戶回應(或網路回應等)的所有操作都是異步的。您需要使用 Promise、Observable 或其他一些回呼來等待和處理呈現給用戶的對話結果。如所寫,您的代碼將立即執行下一行 ( return component.confirmed),這將回傳初始值confirmed。
你還沒有包含 openDialog() 的實作,所以不清楚它是什么樣子的,但是任何對話框組件都會回傳一個 Promise 或 Observable 到最終值,你可以直接從 canDeactivate 回傳(如果它恰好是Promise<boolean> 或 Observable<boolean>) 或通過映射操作將其映射到布林值(Promise.then() 用于 Promises,或 pipe(map()) 用于 Observable)。例如,Angular Material mat-dialog 組件從其 open() 方法回傳一個 Obervable<boolean>,您可以直接從 canDeactivate 回傳它。
2. Angular的瀏覽器歷史管理存在bug
有關 StackOverflow 的相關問題,請參見此處,錯誤報告請參見此處。基本上,即使導航被 canDeactivate 拒絕,它仍然會更新瀏覽器歷史記錄并進入不良狀態(反復嘗試回傳最終會將您導航到上一頁并可能完全遠離應用程式)。根據報告,這是固定的,但是我發現我仍然需要使用這個“隱藏”選項來避免這個錯誤:
router.canceledNavigationResolution = 'computed';
我已經寫了一個 Stackblitz 來完成你所描述的,通過在這里等待確認對話框回應(并實作路由器歷史修復): https ://stackblitz.com/edit/angular-ivy-gaa2bh?file=src /app/before-leave-guard.ts
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/485630.html
上一篇:錯誤TS2322:型別“數字”不可分配給型別“字串”。[currentPrice]="listing.price"
