ngAfterContentInit钩子无法按预期工作

时间:2020-08-23 20:25:11

标签: angular

我有一个带导航栏的Angular应用。该导航栏有2种状态-用于登录的用户和尚未登录的用户。我的目标是通过*ngIf语句和ng-template块更改此导航栏状态,以便登录的用户可以看到他的姓名和头像。这部分工作正常,但是如果使用ngAfterContentInit钩子不会加载用户的数据,但是如果使用ngDoCheckngAfterViewChecked钩子,它的工作就可以正常进行。这些解决方案不适合我,因为它们导致对后端的请求过多,并且用户登录后只需设置一个请求即可设置其数据。这是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);
}

任何帮助和提示将不胜感激。

1 个答案:

答案 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">