使用 service/broadcasting 的组件通信:Angular2

Component communication using service/broadcasting : Angular2

大家好我是angular2的初学者。我正在创建一个用于学习目的的小型演示应用程序。

app.component.ts

template: `
    <header-content></header-content>
    <main-content></main-content>
    <footer-content></footer-content>
  `

在我的 header 中,我有一个导航部分,例如主页、登录等。

Main-content-template结构

<div class="container main">
        <div class="row">
          <router-outlet></router-outlet>
        </div>
 </div> 

如您所见,我已将 header 和页脚部分 link 的 router-outlet 放在 main-content.

默认我在登录页面/login.

我每个 link 都有一个单独的组件。

我想要的是,当用户点击登录页面上的提交按钮时,我将他重定向到其他一些 xyz page.But,同时我希望我的登录名 link 从 header导航并显示用户名。

   <li *ngIf='!isUserLoggedIn'><a routerLink="/login">Login</a></li>
   <li *ngIf='isUserLoggedIn'><a>Welcome {{user}}</a></li>

HeaderComponent.ts

@Component({
  moduleId : module.id,
  selector : 'header-content',
  templateUrl: 'Header.html',
  providers: [LoginService]
})

export class HeaderComponent implements OnInit {
  isUserLoggedIn = false;
  user : string;

  constructor(private loginService: LoginService) { }

  getUserName() :void {
      this.user = this.loginService.getUserName(); // reading data from localstorage on page refresh
      if(this.user) {
        this.isUserLoggedIn = true;
      }
  }

  ngOnInit(): void {
     this.getUserName();
     // Will fire everytime other component use the setter this.loginService.setLogged()
     this.loginService.getLogged().subscribe((logged) => {
         console.log('Welcome===>', logged);
     });
  }
}

Login-Service.ts

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

@Injectable()

export class LoginService {
    username : string;

        private logged: boolean;
        private subject: Subject<boolean> = new Subject<boolean>();

        setLogged(logged: boolean): void {
            this.logged = logged;
            this.subject.next(logged);
        }

        getLogged() {
            return this.subject.asObservable();
        }


    constructor() {
        if(localStorage.getItem('userName')){
            this.username = localStorage.getItem('userName');
        }
    }

    getUserName():string {
        if(this.username) 
         return this.username;
    }
}

我在 Whosebug 上阅读了很多其他问答博客,并且我尝试使用 observable,正如您在代码中看到的那样。但是当我点击提交按钮时,不会调用 ngOnInit() ( this.loginService.getLogged().subscribe((logged) => { ) 中的代码行来更新 isUserLoggedIn 的值。

我怎样才能广播或触发某种机制,有哪些方法和最好的方法。

我不知道我在做什么错误。

我的另一个问题是 header-content 中的方法如何与其兄弟 main-contentfooter-content 以及 parent my-app 组件 section.As 在许多问题中的答案是有 parent child 组件,但没有兄弟姐妹。

感谢任何帮助!!!

谢谢

在您的 login-service 中,您调用 returns username 的方法。 这意味着你有一个承诺。

所以回到您的 headerComponent 中,将 get 函数更改为:

getUserName() :void {
      this.user = this.loginService
                      .getUserName()
                      .success(data => {
                             this.isUserLoggedIn = true;
                      }
  }

我相信这会根据我在这里看到的内容解决您的问题。 我建议创建一个工作片段 ;)

更新 根据您的评论,我建议您使用 BehaviorSubject,这让您可以轻松地从服务向组件广播您想要的任何内容(从布尔值到对象等)。

这是一个基于您的案例的示例:

在您的登录服务中(我只附上实现此操作的代码):

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

@Injectable()

export class LoginService {

    userUpdated: any;

    constructor() {
        this.userUpdated = new BehaviorSubject<any>(false);
    }

    getUserName() :void {
        this.user = this.loginService
                        .getUserName()
                        .success(data => {
                            this.userUpdated.next(true);
                            return data;
                        }
    }

}

接下来你转到headerComponent代码并像这样编辑它以订阅这个:

@Component({
  moduleId : module.id,
  selector : 'header-content',
  templateUrl: 'Header.html',
  providers: [LoginService]
})

export class HeaderComponent implements OnInit, OnDestroy {
  isUserLoggedIn = false;
  user : string;
  sub: any;

  constructor(private loginService: LoginService) { }

  ngOnInit(): void {
    this.sub = this.loginService.userUpdated.subscribe(
      data => {
        if(data.username) {
          this.isUserLoggedIn = true;
      }
    );

  }

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

在做了太多实验之后我发现了我正在做的错误,我没有创建一个单独的登录服务,而是将其作为共享服务,我从每个组件中删除了声明 providers:[LoginService] 并将其放置app.module.ts 文件中的代码行。

HeaderComponent.ts

 ngOnInit(): void {
     this.getUserName();
     // Will fire everytime other component use the setter this.sharedService.setLogged()
      this.sharedService.getLogged().subscribe((logged) => {
        console.log("logged==", logged);
        this.isUserLoggedIn = logged;
        this.user = this.sharedService.getUserName();
      });
  }