代码之家  ›  专栏  ›  技术社区  ›  Stephane

为什么在用户登录和注销时不更新头模板中可观察到的isLoggedIn?

  •  0
  • Stephane  · 技术社区  · 7 年前

    我的 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 当登录状态更改时,标头模板中的observable不会得到更新。

    编辑:我通过跳过 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>
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Sunil Singh    7 年前

    我看这有问题 isAuthenticated . 它总是在回归新事物 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);
                }
            );
        }
    
    }
    

    推荐文章