0

我正在开发一个 Angular 2+ 应用程序。我发现在 AngularJS 中实现相对简单的东西非常困难。

我希望我的顶部导航LOG IN在用户未登录和登录时显示一个按钮LOG OUT

我一直在尝试各种事情,但我无法让它正常工作。我希望它在整个应用程序中始终如一地工作,并且无论重新加载(它存储isLoggedInlocalStorage


我目前的实现根本不起作用,但我会在这里分享它,这样你就可以告诉我我是否至少在正确的轨道上某个地方。

顶部导航.component.html

<p class="nav-item my-2 my-lg-0" *ngIf="!isLoggedIn | async"><a class="nav-link" routerLink="/login" routerLinkActive="active">Login</a></p>
  <p class="nav-item my-2 my-lg-0" *ngIf="isLoggedIn | async"><a class="nav-link" routerLink="//logout" routerLinkActive="active">Logout</a></p>

顶部导航.component.ts

export class TopNavigationComponent implements OnInit {

  @ViewChild('topnav') topnav: ElementRef;
  //isLoggedIn: boolean;

  isLoggedIn: Observable<Boolean>;

  constructor( private authService: AuthService, private logger: LoggerService ) { }

  ngOnInit() {
    this.isLoggedIn = this.authService.getIsLoggedIn();
  }

auth.service.ts

@Injectable()
export class AuthService {

  loggedIn$: Subject<Boolean> = new Subject<Boolean>();

  constructor(private logger: LoggerService) {
    let isLoggedInLocalStore = (localStorage.getItem('isLoggedIn') === 'true');
    if (!isLoggedInLocalStore) {
      isLoggedInLocalStore = false;
      localStorage.setItem('isLoggedIn', isLoggedInLocalStore.toString());
    }
  }

  getIsLoggedIn(): Observable<Boolean> {
    //return (localStorage.getItem('isLoggedIn') === 'true');
    return this.loggedIn$.asObservable();
  }

  login(): void {
    // TODO
    this.logger.log("AuthService | Login clicked...");
    localStorage.setItem('isLoggedIn', 'true');
    this.loggedIn$.next(true);
  }

  logout() {
    // TODO
    localStorage.setItem('isLoggedIn', 'false');
    this.loggedIn$.next(false);
  }

}
4

3 回答 3

1

我不确定我的回答是否会对您有所帮助。为此,我创建了名为 GlobalEventsManager 的服务。

import { Injectable } from '@angular/core';
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { Observable } from "rxjs/Observable";

@Injectable()
export class GlobalEventsManager {

    private _showMainMenu: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
    public showMainMenuEmitter: Observable<boolean> = this._showMainMenu.asObservable();

    constructor() {
      this.showMainMenu(Boolean(localStorage.getItem('currentUser')));
    }

    showMainMenu(ifShow: boolean) {
      this._showMainMenu.next(ifShow);
    }


}

在这个例子中,我显示/隐藏菜单取决于用户是登录还是注销。如何使用它(不是完整的类代码,只是示例):

import { GlobalEventsManager } from "../../core/_helpers/index";
export class ExampleClass implements OnInit {
   constructor(private globalEventsManager: GlobalEventsManager) {

   }

   login(): void {
       //Your code
       ...
       //Show main menu for authentificated users
       this.globalEventsManager.showMainMenu(true)
   }

   logout(): void {
      //Your code 
      ...
      //Hide main menu
      this.globalEventsManager.showMainMenu(false)
   }

}   

以及如何在组件中使用它(不是完整代码,只是示例):

import { GlobalEventsManager } from '/_helpers/index';


@Component({
    selector: "main-menu",
    templateUrl: "main-menu.component.html",
})

export class MainMenuComponent  {
    showMainMenu: boolean = false;


    constructor(private globalEventsManager: GlobalEventsManager) {
        this.globalEventsManager.showMainMenuEmitter.subscribe((mode) => {
            // mode will be null the first time it is created, so you need to igonore it when null
            if (mode !== null) {
              this.showMainMenu = mode;
            }
        });
    }

    //Other code 
    ...
    ...
    ...
}

现在你有 boolean showMainMenu 变量取决于你的用户。

PS:您也可以将此 GlobalEventsManager 用于其他目的。例如。管理应该影响您的应用程序的全局事件。

PPS:大约 1 年前,我在 stackoverflow 上找到了类似的解决方案。只是我找不到链接。因此试图在这里描述解决方案。

谢谢。希望它会帮助你。

于 2017-10-25T07:35:35.673 回答
0

您使用的是正确的方法,但稍作修改:

在您的 top-navigation.component.ts 中:

isLoggedIn:boolean;

constructor(private cd:ChangeDetectorRef, private authService: AuthService, private logger: LoggerService ) { 
      this.authService.getIsLoggedIn().subscribe((loggedIn:boolean) => {
      this.isLoggedIn = loggedIn;
      this.cd.markForCheck();}
}

在您的 auth.service.ts 中:

getIsLoggedIn(): Subject<Boolean> {
    return this.loggedIn$;
}

并删除 | 与您的 HTML 异步。

每当用户登录时,您都会从服务中发送 true throw 您的主题,并且所有订阅者都会收到通知,并且在用户注销时也是如此。

于 2017-10-25T07:16:10.050 回答
-2

您正在查看的是使用中央共享服务甚至为此目的使用事件发射器。

您必须将它与 Local Storage 结合使用。当用户登录时,您需要将数据保存在共享服务和本地存储中。因此,这将确保他是否注销您可以将所有数据保存在本地存储中并检查用户是否已登录。

当他按下注销按钮时,从本地存储和共享服务中删除本地值。

现在如何在这里显示登录和注销按钮是事件发射器和共享服务将发挥他们的魔力的地方。一旦将值添加到共享服务,它将发出一个 Observable,该 Observable 将被 Observing 组件和在 Observing 组件中使用 If 和 Else 来显示按钮。

工作示例

于 2017-10-25T05:09:20.717 回答