angular - 为什么当我在 Angular 中路由时没有触发警卫?
问题描述
我创建了惰性路由:一个用于 app shell 模块,另一个用于 auth 模块。
当我单击登录时,我会重定向到 shell 应用程序,这没关系。
但是当我点击注销并重定向到主路由(为了触发警卫)时,警卫似乎没有调用。
我怎么知道?因为单击注销后我看不到控制台输出。
它甚至不会触发问题所在的守卫。所以我不会重定向到登录页面。
是的,当然我可以直接导航到登录路线,但我想为我做这件事。
所以我创建了一个简单的应用程序来演示这里和codesandbox.io中的问题
import { BrowserModule } from "@angular/platform-browser";
import { Injectable, NgModule } from "@angular/core";
import { Component } from "@angular/core";
import {
ActivatedRouteSnapshot,
CanActivate,
CanActivateChild,
CanLoad,
Router,
RouterModule,
RouterStateSnapshot,
UrlTree
} from "@angular/router";
import { CommonModule } from "@angular/common";
import { Observable, of } from "rxjs";
let loggedIn = false; // <--- this is demo. it's set if the user login or not.
@Component({
template: '<button (click)="login()">login</button>'
})
export class LoginComponent {
constructor(private router: Router) {}
login() {
console.log("in login");
loggedIn = true;
this.router.navigate(["/"]);
}
}
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([{ path: "", component: LoginComponent }])
],
declarations: [LoginComponent]
})
export class AuthModule {}
///////////////////////////////
@Injectable()
export class IsLoggedInGuard implements CanActivate, CanActivateChild, CanLoad {
constructor(private readonly router: Router) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> {
return this.isAuthenticated(state.url);
}
canActivateChild(): Observable<boolean | UrlTree> {
return this.isAuthenticated();
}
canLoad(): Observable<boolean | UrlTree> {
return this.isAuthenticated();
}
private isAuthenticated(url?: string): Observable<boolean | UrlTree> | any {
if (!loggedIn) {
return this.router.createUrlTree(["/auth"], {
queryParams: { url }
});
}
return true;
}
}
////
@Component({
template: '<button (click)="logout()">logout</button>'
})
export class ShellComponent {
constructor(private router: Router) {}
logout() {
console.log("in logout");
loggedIn = false;
this.router.navigate(["/"]);
}
}
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([{ path: "", component: ShellComponent }])
],
declarations: [ShellComponent]
})
export class ShellModule {}
@Component({
selector: "app-root",
template: `<router-outlet></router-outlet>`
})
export class AppComponent {
title = "CodeSandbox";
}
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: "",
loadChildren: () => Promise.resolve(ShellModule),
canActivate: [IsLoggedInGuard]
},
{ path: "auth", loadChildren: () => Promise.resolve(AuthModule) }
])
],
providers: [IsLoggedInGuard],
bootstrap: [AppComponent]
})
export class AppModule {}
解决方案
您不能这样做,因为您已经在同一个route
“canActivate
决定是否可以激活路线”上,但在您的情况下,它在您登录时导航到它后已经被激活。
即使将onSameUrlNavigation
配置更改为reload
,或RouteReuseStrategy
用于在导航到同一路由时重新加载组件,即使这样也不起作用,因为这只会重新加载组件而不会canActivate
再次触发防护(因为路由已经激活)。
在您的情况下,最好在注销时将用户重定向到登录页面。
推荐阅读
- dataframe - 在 Pandas Dataframe Groupby.agg() 中将多列组合为 lambda 函数的参数
- azure - 从 Azure DevOps 管道 YAML 文件运行“az artificats”命令
- ruby - Ruby 参数错误,试图将矩阵转置 90 度
- javascript - setState() 的异步性质不显示来自父组件的更新道具
- c++ - 使用 std::istream_iterator 时,它似乎跳过了空文件行 - 如果可能,我该如何避免这种情况?
- git - 重新合并由于错误解决冲突而失败的恢复合并
- python - 烧瓶渲染模板()不起作用,TypeError:'NoneType'对象不可迭代
- wso2 - 是否建议在 wsois 5.9.0 中为身份、共享、bps、同意和度量数据库使用不同的数据库?
- javascript - 如何从 Angular JS 的列表中删除 $id?
- spring - 在线程池环境中清除线程局部变量