簡體   English   中英

ngIf ExpressionChangedAfterItHasBeenCheckedError

[英]ngIf ExpressionChangedAfterItHasBeenCheckedError

我正在嘗試從我的 Angular 6 應用程序的導航欄菜單中隱藏登錄項。 我有一個像下面這樣的AuthService

import { Injectable, Inject } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { map } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { JwtHelperService } from '@auth0/angular-jwt';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private url: string;
  private loggedIn = new BehaviorSubject<boolean>(false);
  isLoggedIn$ = this.loggedIn.asObservable();

  constructor(private http: HttpClient, private jwtHelper: JwtHelperService, @Inject('BASE_URL') baseUrl: string) {
    this.url = baseUrl + 'api/auth';
    this.loggedIn.next(this.isLoggedIn());
  }

  login(credentials) {
    const headers = new HttpHeaders({ 'Content-Type': 'application/json' });

    return this.http.post<any>(`${this.url}/login`, JSON.stringify(credentials), { headers: headers }).pipe(
      map(response => {
        if (response && response.token) {
          localStorage.setItem('token', response.token);
          this.loggedIn.next(true);

          return true;
        }        

        return false;
      })
    );
  }

  logout() {
    localStorage.removeItem('token');
    this.loggedIn.next(false);
  }

  isLoggedIn() {
    return !this.jwtHelper.isTokenExpired();
  }
}

這是我在NavMenuComponent

export class NavMenuComponent implements OnInit, OnDestroy {
  isExpanded = false;
  isLoggedIn: boolean;
  authSubscription: Subscription;

  constructor(private router: Router, private authService: AuthService) {}

  ngOnInit() {
    this.authSubscription = this.authService.isLoggedIn$
      .subscribe(loggedIn => this.isLoggedIn = loggedIn);
  }

  ngOnDestroy() {
    this.authSubscription.unsubscribe();
  }

  onLogout() {
    this.authService.logout();
    this.router.navigate(['/login']);
  }

  collapse() {
    this.isExpanded = false;
  }

  toggle() {
    this.isExpanded = !this.isExpanded;
  }
}

而且,這是 html:

<li *ngIf="!isLoggedIn" class="nav-item" [routerLinkActive]="['link-active']">
  <a class="nav-link" [routerLink]="['/login']">Login</a>
</li>

但是,當我運行它時,出現以下錯誤:

錯誤:ExpressionChangedAfterItHasBeenCheckedError:檢查后表達式已更改。 以前的值:'ngIf: true'。 當前值:'ngIf:false'。

我確實讀過這個錯誤,但我不明白如何解決它。 有什么幫助嗎?

我的猜測是,它與您設置的初始值的方式做loggedIn在服務的構造函數: this.loggedIn.next(this.isLoggedIn());

嘗試僅在您的類中聲明變量,並僅在您的構造函數中將其設為new BehaviourSubject()

就像是:

 private url: string;
  private loggedIn: BehaviorSubject<boolean>;
  isLoggedIn$: Observable<boolean>;

  constructor(private http: HttpClient, private jwtHelper: JwtHelperService, @Inject('BASE_URL') baseUrl: string) {
    this.url = baseUrl + 'api/auth';
    this.loggedIn = new BehaviourSubject<boolean>(this.isLoggedIn());
    this.isLoggedIn$ = this.loggedIn.asObservable()
  }

如果這有什么改變,請告訴我

您嘗試使用方法而不是屬性來返回 AuthService 上的可觀察對象

isLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject(false);

isLoggedIn$() {
    return this.isLoggedIn.asObservable();
}

您可以使用 setTimeout 解決此錯誤。

  export class NavMenuComponent implements OnInit, OnDestroy {
  isExpanded = false;
  isLoggedIn: boolean;
  authSubscription: Subscription;

  constructor(private router: Router, private authService: AuthService) {}

  ngOnInit() {
   setTimeout(() => {
    this.authSubscription = this.authService.isLoggedIn$
      .subscribe(loggedIn => this.isLoggedIn = loggedIn);
   });
  }

  ngOnDestroy() {
    this.authSubscription.unsubscribe();
  }

  onLogout() {
    this.authService.logout();
    this.router.navigate(['/login']);
  }

  collapse() {
    this.isExpanded = false;
  }

  toggle() {
    this.isExpanded = !this.isExpanded;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM