我正在 Angular 中创建我的第一次登录。一切正常,用户已登录,并且他被重定向到 GiveDashboardComponent 并在导航栏上显示而不是“登录”按钮 - 显示“注销”,注销时则相反。问题是,只有当我手动刷新页面时,这些更改才会出现在我面前(这就是我知道它的工作原理)。在 Angular 中正确的做法是什么,或者我在当前代码中选择了一些错误的方法?
我的登录组件:
export class LoginComponent implements OnInit {
user: User = new User();
errorMessage: string = '';
constructor(
private authService: AuthenticationService,
private router: Router,
public sharedService: SharedService
) {}
ngOnInit(): void {
if (this.authService.currentUserValue?.id) {
this.router.navigate(['/give-dashboard']);
}
}
exit() {
this.sharedService.showLoginComponent = false;
}
login() {
this.authService.login(this.user).subscribe(
(data) => {
this.router.navigate(['/give-dashboard']);
},
(err) => {
this.errorMessage = 'Username or password is incorrect.';
console.log(err);
}
);
}
}
导航栏组件:
export class NavBarComponent implements OnInit {
isLoggedIn = false;
user: User = new User();
constructor(
private router: Router,
private authService: AuthenticationService,
private sharedService: SharedService
) {}
ngOnInit(): void {
this.authService.loggedUser.subscribe((res) => {
if (res) {
this.isLoggedIn = true;
} else {
this.isLoggedIn = false;
}
});
}
showLogin() {
this.sharedService.showLoginComponent = true;
}
logout() {
this.authService.logout();
this.router.navigate(['']);
this.isLoggedIn = false;
}
}
还有仪表板组件(我尝试简单地进行导航,但这显然不是方法)
export class GiveDashboardComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit(): void {
this.router.navigate(['/give-dashboard']);
}
}
和身份验证服务:
export class AuthenticationService {
public currentUser: Observable<User>;
private currentUserSubject: BehaviorSubject<User>;
private isLoggedIn = new BehaviorSubject<boolean>(this.userIsLoggedIn());
public loggedUser = this.isLoggedIn.asObservable();
constructor(private http: HttpClient) {
let storageUser;
const storageUserAsStr = localStorage.getItem('currentUser');
if (storageUserAsStr) {
storageUser = JSON.parse(storageUserAsStr);
}
this.currentUserSubject = new BehaviorSubject<User>(storageUser);
this.currentUser = this.currentUserSubject.asObservable();
}
public get currentUserValue(): User {
return this.currentUserSubject.value;
}
login(user: User): Observable<any> {
return this.http.post<User>(API_URL + '/sign-in', user).pipe(
map((res) => {
if (res) {
// set session-user
this.setSessionUser(res);
} else {
return false;
}
return res;
})
);
}
register(user: User): Observable<any> {
return this.http.post<User>(API_URL + '/sign-up', user).pipe(
map((res) => {
if (res) {
this.setSessionUser(res);
} else {
return false;
}
return res;
})
);
}
setSessionUser(user: User) {
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
}
logout() {
localStorage.removeItem('currentUser');
this.currentUserSubject.next(new User());
// this.currentUserSubject.next(null);
}
refreshToken(): Observable<any> {
return this.http.post(
API_URL + '/refresh-token?token=' + this.currentUserValue?.refreshToken,
{}
);
}
userIsLoggedIn() {
return !!localStorage.getItem('currentUser');
}
}
这个问题看起来像是changeDetection有问题。我会选择 RxJS 库中的 Observable 和 subject。这允许组件订阅更改并相应更新。您可以在 AuthenticationService 中使用BehaviorSubject 来保存用户的当前状态。
认证服务示例:
export class AuthenticationService {
private currentUserSubject: BehaviorSubject<User | null>;
public currentUser$: Observable<User | null>;
constructor(private http: HttpClient) {
let storageUser: User | null = null;
const storageUserAsStr = localStorage.getItem('currentUser');
if (storageUserAsStr) {
storageUser = JSON.parse(storageUserAsStr);
}
this.currentUserSubject = new BehaviorSubject<User | null>(storageUser);
this.currentUser$ = this.currentUserSubject.asObservable();
}
setSessionUser(user: User) {
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
}
logout() {
localStorage.removeItem('currentUser');
this.currentUserSubject.next(null);
}
// ... remaining code
}
并在您的 NavBarComponent 中,订阅 currentUser:
NavBarComponent 的 TS.组件:
export class NavBarComponent implements OnInit {
isLoggedIn = false;
constructor(
private router: Router,
private authService: AuthenticationService,
private sharedService: SharedService
) {}
ngOnInit(): void {
this.authService.currentUser$.subscribe((user) => {
this.isLoggedIn = !!user;
});
}
// ... remaining code
}
在这种方法中,每当用户的状态发生变化(登录或注销)时,AuthenticationService 都会更新其 currentUserSubject,然后将更改发送给其所有订阅者。
对我来说,我只是保持非常简单,如果这是我的代码,我将添加这个简单的代码 位置.reload();这里=>
login() {
this.authService.login(this.user).subscribe(
(data) => {
// add it here and thank me later :)
location.reload()
this.router.navigate(['/give-dashboard']);
},
(err) => {
this.errorMessage = 'Username or password is incorrect.';
console.log(err);
}
// and of course also here
ngOnInit(): void {
if (this.authService.currentUserValue?.id) {
location.reload()
this.router.navigate(['/give-dashboard']);
}
}