我有一个带导航栏的Angular应用。该导航栏有2种状态-用于登录的用户和尚未登录的用户。我的目标是通过*ngIf
语句和ng-template
块更改此导航栏状态,以便登录的用户可以看到他的姓名和头像。这部分工作正常,但是如果使用ngAfterContentInit
钩子不会加载用户的数据,但是如果使用ngDoCheck
或ngAfterViewChecked
钩子,它的工作就可以正常进行。这些解决方案不适合我,因为它们导致对后端的请求过多,并且用户登录后只需设置一个请求即可设置其数据。这是HTML部分,仅供参考:
<nav *ngIf="subscr | async as auth; else elseBlock" class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div class="img-logo-block">
<img class="navbar-brand" src="assets/static/img/logo.svg" alt="Logo" (click)="gt_myprofile()">
</div>
<div class="container">
<div class="collapse navbar-collapse navmenu" [ngClass]="{ 'show': navbarOpen }" id="navbarSupportedContent">
<ul class="navbar-nav">
<li class="nav-item sub">
<a class="nav-link unselectable" (click)="gt_myprofile()"><span
class="icon icon-profile"></span> profile
</a>
</li>
<li class="nav-item sub">
<a class="nav-link unselectable" routerLink="/contacts" routerLinkActive="nav-link-active"><span
class="icon icon-contacts"></span>
contacts
</a>
</li>
</ul>
<div ngbDropdown class="profile">
<a class="nav-dropdown dropdown-toggle" id="dropdownBasic1" ngbDropdownToggle>
{{user?.first_name}}
<img *ngIf="!user?.avatar;else userAvatar" src="assets/static/img/avatar.jpg" class="nav-avatar">
<ng-template #userAvatar><img src="{{user?.avatar}}" alt="" class="nav-avatar"></ng-template>
</a>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<a ngbDropdownItem class="profile-dropdown-link" (click)="gt_myprofile()">profile</a>
<a ngbDropdownItem class="profile-dropdown-link" (click)="gt_allContacts()">Contacts</a>
<a ngbDropdownItem class="profile-dropdown-link" (click)="gt_settings()">settings</a>
</div>
</div>
</nav>
<ng-template #elseBlock>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div class="collapse navbar-collapse" [ngClass]="{ 'show': navbarOpen }" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" routerLink="/about" routerLinkActive="nav-link-active">about<span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/cooperation" routerLinkActive="nav-link-active">cooperation</a>
</li>
</ul>
<!-- end navbar-nav -->
<div class="search-form">
<a class="nav-link" (click)="notif_on()" (click)="home()">Логин</a>
</div>
</div>
</div>
</nav>
</ng-template>
与TS组件相关的部分:
ngOnInit() {
this.subscr = this.auth_service.currentUser;
}
此钩子有效
ngAfterViewChecked() {
// check if user is logged in
if (localStorage.getItem('currentUser') !== null) {
this.auth_service.getUser().subscribe(
data => {this.user = data}
);
}
}
这不是
ngAfterContentInit() {
// check if user is logged in
if (localStorage.getItem('currentUser') !== null) {
this.auth_service.getUser().subscribe(
data => {this.user = data}
);
}
}
验证服务相关部分:
private currentUserSubject: BehaviorSubject<User>;
public currentUser: Observable<User>;
constructor(private http: HttpClient) {
this.currentUserSubject = new BehaviorSubject<User>
(JSON.parse(localStorage.getItem('currentUser')));
this.currentUser = this.currentUserSubject.asObservable();
}
public get currentUserValue(): User {
return this.currentUserSubject.value;
}
login(email: string, password: string) {
return this.http.post<any>(`${environment.apiUrl}/api/auth/`, { email, password })
.pipe(map(user => {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
this.currentUser = this.currentUserSubject.pipe(filter(value => !!value)).asObservable();
return user;
}));
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
this.currentUserSubject.next(null);
}
任何帮助和提示将不胜感激。
答案 0 :(得分:1)
会议结束后,我终于明白了问题所在。
服务代码
// stored current user info
// tslint:disable-next-line: variable-name
private _user: User = JSON.parse(localStorage.getItem('currentUser'));
// current user subject
currentUserSubject: BehaviorSubject<User> = new BehaviorSubject(this.user);
// get current userInfo
get user() {
return this._user;
}
// set user info
set user(user: User) {
this._user = user;
if (this._user) {
localStorage.setItem("currentUser", JSON.stringify(this.user));
} else {
localStorage.removeItem("currentUser");
}
this.currentUserSubject.next(this.user);
}
get userChanges() {
return this.currentUserSubject.asObservable();
}
login(email: string, password: string) {
return this.http.post<any>("", { email, password }).pipe(
map(user => {
// store user details and jwt token in local storage to keep user logged in between page refreshes
this.user = user;
return this.user;
})
);
}
logout() {
this.user = null;
}
getUser(id: number = this.user.id) {
return this.http.get<any>((`${environment.apiUrl}/api/user/${id}`));
}
导航栏组件代码
ngOnInit() {
this.auth_service.userChanges.pipe(filter(user => !!user)).subscribe(user => {
this.auth_service.getUser(user.id).subscribe(
data => {this.user = data}
);
});
}
模板代码
<nav *ngIf="user; else elseBlock" class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">