我的AppModule
导入了CoreModule
@NgModule({
providers: [
LoginService
],
})
export class CoreModule {
其本身在全局范围内提供LoginService
。
@Injectable()
export class LoginService {
constructor(
private router: Router,
private authService: AuthService
) { }
login(username: string, password: string) {
this.authService.login(username, password).subscribe(
response => {
this.router.navigate(['users']); // TODO Check that all router.navigate don't use hard coded strings
},
error => {
console.log(error);
}
);
}
logout() {
this.authService.logout().subscribe(
response => {
this.router.navigate(['login']);
},
error => {
console.log(error);
}
);
}
}
还有一个AuthService
用于服务器端登录或注销,并将登录状态保留在浏览器本地存储中。
public isAuthenticated(): Observable<boolean> {
if (this.tokenService.accessTokenExpired()) {
if (this.tokenService.refreshTokenExpired()) {
return of(false);
} else {
return this.refreshAccessToken()
.pipe(
map(response => {
if (response) {
return true;
}
}),
catchError((error, caught) => {
return of(false);
})
);
}
}
return of(true);
}
根据登录状态,应该显示或不显示标题模板。
<mat-toolbar color="primary" *ngIf="isLoggedIn$ | async as isLoggedIn">
此标头组件保持登录状态。
isLoggedIn$: Observable<boolean>;
ngOnInit() {
this.isLoggedIn$ = this.authService.isAuthenticated();
}
logout(): void {
this.loginService.logout();
}
导航正常,但是页眉模板需要刷新页面才能与登录状态保持同步。
当登录状态更改时,感觉标题模板中的isLoggedIn
并没有得到更新。
该代码已被删除。
编辑:我通过跳过ngIf
方式并使用多种布局来解决此问题。
const routes: Routes = [
{
path: '',
component: LoginLayoutComponent,
children: [
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'login',
component: LoginComponent
}
]
},
{
path: '',
component: HomeLayoutComponent,
canActivateChild: [AuthGuardService],
children: [
{
path: 'users',
component: UsersComponent,
},
{
path: 'detail/:id',
component: UserComponent,
},
{
path: 'dashboard',
component: DashboardComponent,
data: {
expectedRole: 'admin'
}
},
{
path: 'home',
loadChildren: './views/home/home.module#HomeModule',
data: {
preload: true,
delay: false
}
},
{
path: 'error',
component: ErrorComponent
},
]
},
];
login
布局:
@Component({
selector: 'app-login-layout',
template: `<router-outlet></router-outlet>`
})
export class LoginLayoutComponent { }
还有一个home
布局:
@Component({
selector: 'app-home-layout',
templateUrl: './home.layout.component.html'
})
export class HomeLayoutComponent { }
及其模板:
<mat-sidenav-container class="example-container">
<mat-sidenav #drawer mode="side" opened role="navigation">
<mat-nav-list>
<a mat-list-item routerLink='/first'>First Component</a>
<a mat-list-item routerLink='/second'>Second Component</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<app-header></app-header>
</mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-container>
答案 0 :(得分:1)
我看到isAuthenticated
有问题。它总是每次都返回新的Observable
。您应该有一个Observable
,通过它可以通知所有Subscription
。
private authSubject = new BehaviorSubject<boolean>(false);
private isLoggedIn$ = this.authSubject.asObservable();
updateLoggedInState(status: boolean){
this.authSubject.next(status);
}
public isAuthenticated(): Observable<boolean> {
return this.isLoggedIn$;
}
@Injectable()
export class LoginService {
constructor(
private router: Router,
private authService: AuthService
) { }
login(username: string, password: string) {
this.authService.login(username, password).subscribe(
response => {
this.router.navigate(['users']); // TODO Check that all router.navigate don't use hard coded strings
this.authService.updateLoggedInState(true);
},
error => {
console.log(error);
this.authService.updateLoggedInState(false);
}
);
}
logout() {
this.authService.logout().subscribe(
response => {
this.router.navigate(['login']);
this.authService.updateLoggedInState(false);
},
error => {
console.log(error);
}
);
}
}
注意:我没有介绍令牌,但是您可以按照自己的方式来处理它。