0

我有 2 个没有任何父子关系的组件。

一个组件是一个简单的login.component.html

<form #loginForm="ngForm" (ngSubmit)="onSubmit()">
  <div class="login-container">
    <mat-form-field appearance="fill">
      <mat-label>Enter your username</mat-label>
      <input
        matInput
        name="username"
        type="text"
        [(ngModel)]="username"
        #usernameCtrl="ngModel"
        required
      />
    </mat-form-field>
    <mat-form-field appearance="fill">
      <mat-label>Enter your password</mat-label>
      <input
        matInput
        name="password"
        [type]="hide ? 'password' : 'text'"
        [(ngModel)]="password"
        #passwordCtrl="ngModel"
        required
      />
      <button
        mat-icon-button
        matSuffix
        (click)="hide = !hide"
        [attr.aria-label]="'Hide password'"
        [attr.aria-pressed]="hide"
      >
        <mat-icon>{{ hide ? "visibility_off" : "visibility" }}</mat-icon>
      </button>
    </mat-form-field>
  </div>
  <div>
    <button
      mat-button
      color="primary"
      [disabled]="!loginForm.form.valid"
      type="submit"
    >
      Login
    </button>
  </div>
</form>

另一个是menu-bar.component.html

<div>
    <h1>Hello world!</h1>
    <h2>I am visible in world all of the time!</h2>
    <div *ngIf="loginSuccessfull"> <menu-app> </menu-app> </div>
</div>

当用户成功登录时,我想显示我的 menu-app.component。我所做的是我定义了一个布尔变量,当用户登录时将其设置为真。

login.component.ts中:

onSubmit() {
    if (this.username === 'a' && this.password === 'a') {
      console.log('login successful');
      this.loginService.updateLoginSuccessfull(true);
    }

menu-bar.component.ts

ngOnInit() {
    this.loginService.loginSuccessfull.subscribe(loginSuccessfull => this.loginSuccessfull = loginSuccessfull);
  }

  ngAfterContentChecked() {
    this.loginService.loginSuccessfull.subscribe(loginSuccessfull => this.loginSuccessfull = loginSuccessfull);
  }

正如你所理解的,这两个组件都在调用一个定义为login.service.ts的服务:

export class LoginService {

  private onLogin = false;
  private onLoginSuccessfull = new BehaviorSubject(this.onLogin);
  loginSuccessfull = this.onLoginSuccessfull.asObservable();

  constructor() { }

  updateLoginSuccessfull(loginSuccessfull: boolean) {
    this.onLoginSuccessfull.next(loginSuccessfull);
  }

}

我错过了什么?有没有其他方法可以动态地进行这种变化检测?谢谢!预期的行为是<menu-app></menu-app>仅在用户登录时才显示。如果用户没有登录,他不应该看到该组件。即使使用成功登录,我实现的方式也不会显示组件。

4

1 回答 1

0

这些组件看起来大部分都很好。您是否对菜单栏组件使用 OnPush 更改检测?您还在 ngOnInit 和 ngAfterContentChecked 的菜单栏组件中创建了 2 个订阅。每次从服务发出值时,这将更新 loginSuccessful 字段两次。如果您使用async pipe. 异步管道自动订阅(和取消订阅)Observable,在使用 OnPush 时会触发变更检测,并减少组件中所需的代码。

菜单栏.component.ts

@Component({
  selector: 'menu-bar',
  templateUrl: './menu-bar.component.html',
  styleUrls: ['./menu-bar.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MenuBarComponent {
  loggedIn$ = this.service.loginSuccessful;

  constructor(private service: LoginService) { }
}
<div>
  <h1>Hello world!</h1>
  <h2>I am visible in world all of the time!</h2>
  <div *ngIf="loggedIn$ | async"> <menu-app> </menu-app> </div>
</div>

https://stackblitz.com/edit/angular-ivy-pzss5d

于 2020-06-04T15:11:44.183 回答