【问题标题】:Component communication using service/broadcasting : Angular2使用服务/广播的组件通信:Angular2
【发布时间】:2016-11-18 14:56:15
【问题描述】:

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

app.component.ts

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

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

主内容模板结构

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

如您所见,我已将页眉和页脚部分链接的路由器出口放置在 main-content 中。

默认我在登录页面/login。

每个链接都有一个单独的组件。

我想要的是当用户点击登录页面上的提交按钮时,我会将他重定向到其他 xyz 页面。但与此同时,我希望我的登录链接从标题导航中隐藏并显示用户名。

   <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;
    }
}

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

我怎样才能广播或触发一些机制,有什么方法和最好的方法。

我不知道自己做错了什么。

我的另一个问题是 header-content 中的方法如何与它的兄弟 ma​​in-contentfooter-content 以及与父 my-app 组件部分。在许多问题中,答案是针对父子组件,但不是针对兄弟姐妹。

感谢任何帮助!!!

谢谢

【问题讨论】:

    标签: angular angular2-components


    【解决方案1】:

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

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

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

    我相信这会根据我在这里看到的内容解决您的问题。 不过,我建议创建一个有效的 sn-p ;)

    更新 根据您的 cmets,我建议您使用 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();
      }
    }
    

    【讨论】:

    • 仅在页面刷新或初始加载时调用。我的问题是我想广播一个事件来通知我的 headerComponent 在单击 loginComponent 中的提交按钮时,isUserLoggendin 值的值必须设置为 true。
    • 那不是你的问题。使用BehaviorSubject 来实现。
    • 我认为您没有正确阅读它。如果你能帮我写一些代码,那将是不胜感激的。
    • 感谢您的解决方案 :-)
    【解决方案2】:

    在做了太多实验后,我发现了我正在做的错误,我没有创建单独的登录服务,而是将其作为共享服务,我从每个组件中删除了声明 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();
          });
      }
    

    【讨论】:

      猜你喜欢
      • 2017-12-23
      • 1970-01-01
      • 2018-10-21
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 2018-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多