Angular ngIf表达式更改TerrithasbeenscheckedError

Angular ngIf表达式更改TerrithasbeenscheckedError,angular,angular-ng-if,angular-changedetection,Angular,Angular Ng If,Angular Changedetection,我试图在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'; impo

我试图在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();
  }
}
下面是html:

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

但是,当我运行此命令时,会出现以下错误:

错误:ExpressionChangedTerrithasBeenCheckedError:表达式已更改 检查后更改。上一个值:“ngIf:true”。现在的 值:“ngIf:false”


我确实读过这个错误,但我不明白如何解决它。有什么帮助吗?

我猜这与您在服务构造函数中设置
loggedIn
初始值的方式有关:
this.loggedIn.next(this.isLoggedIn())

尽量只在类中声明变量,并且只在构造函数中使其成为
新行为主题()

比如:

 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()
  }
私有url:string;
私人loggedIn:行为主体;
isLoggedIn$:可观察;
构造函数(私有http:HttpClient,私有jwtHelper:JwtHelperService,@Inject('BASE_URL')baseUrl:string){
this.url=baseUrl+'api/auth';
this.loggedIn=新行为主体(this.isLoggedIn());
this.isLoggedIn$=this.loggedIn.asObservable()
}

如果这改变了什么,请告诉我。如果您尝试使用方法而不是属性来返回AuthService上的可观察对象,请告诉我

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

isLoggedIn$() {
    return this.isLoggedIn.asObservable();
}
isLoggedIn:BehaviorSubject=newbehaviorsubject(false);
isLoggedIn$(){
返回这个.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;
  }
}

不幸的是,html没有发布到帖子中,请更新它。@AlexanderLeonov抱歉!已更新。此错误将仅出现在您的开发环境中。如果在部署代码时启用prod模式,它就会消失。另一方面,如果直接使用异步管道,则不必管理isLoggedIn等状态,angular也将负责取消订阅。因此,您不需要执行此操作。authSubscription.unsubscribe();也没有。这没有帮助。@ataravati有可能在stackblitz中制造此问题吗?
  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;
  }
}