Angular2 - 不同级别的组件之间的持久服务

Posted

技术标签:

【中文标题】Angular2 - 不同级别的组件之间的持久服务【英文标题】:Angular2 - Persistent service between components on different levels 【发布时间】:2017-03-31 07:06:54 【问题描述】:

我一天中的大部分时间都在为此苦苦挣扎。基本上我的应用程序布局是这样的

app.component.ts
  -- navigation.component.ts : i.e this selector is in the app.component
  -- router-outlet

基本上,导航栏是我所有登录逻辑的地方,我正在使用 Firebase,这就是奇迹发生的地方,用户登录并且他们的图像在右上角,他们的名字等等。这一切都很可爱。我的问题是我想与其他组件共享这些数据。现在,在前面的一些有用建议之后,我设置了一个服务,将数据从导航组件传递到显示的其他组件之一,这是一个动态组件,这意味着当您单击链接时,它会动态加载,而导航组件保持静态因为它与路由器插座处于同一水平。因此,当您第一次访问页面时,使用我的服务,数据似乎没有问题,我想这是因为构造函数触发一次并且一切都按预期工作,但是当您返回时..什么都没有..没有用户数据传递给该组件,并且因为导航组件不会执行 ngOnInit,除非您在该路线上首次加载站点时。我希望我已经很好地解释了这一点,我对 angular2 相对较新,所以仍在学习。在我的脑海中,也许这可以通过更高级的可观察对象或事件发射器以某种方式实现??

SERVICE.TS

import  Injectable  from '@angular/core';
import  Subject     from 'rxjs/Subject';

// https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

@Injectable()
export class UserdataService 
  // Observable string sources
  private shareUserDataSRC = new Subject<string>();

  // Observable string streams
  userDataAvailable$ = this.shareUserDataSRC.asObservable();


  passUserToService(userdata: string) 
    this.shareUserDataSRC.next(userdata);
    console.log(" service " + userdata);
  



导航.TS

    import  Component, OnInit, Input  from '@angular/core';
    import  Router  from '@angular/router';
    import  UserdataService      from '../userdata.service';

    @Component(
    selector: 'app-navigation',
    template: `
            <header class="mast-head">
                <ul class="list-reset logged-in">
                    <li class="user-welcome">
                        <span>Hi, </span>
                        <a class="go-to-profile" href="#"> user?.name </a>
                        <i class="open-options"></i>
                    </li>
                </ul>
            </header>

            <aside class="side-drawer">

            </aside>
    `,
    styleUrls: ['./navigation.component.css']
    )
    export class NavigationComponent implements OnInit  

    user      = ;

    constructor(  private router: Router, private shareUser: UserdataService) 

    


    ngOnInit() 
        console.log(this.user);
    


        private _changeState(user: any = null) 
        if(user) 
        this.user      = this._getUserInfo(user)
         else 
        this.user      = ;
        
    

    private _getUserInfo( user: any ): any 

        if(!user) 
        return ;
        

        let data     = user.auth.providerData[0];

        this.shareUser.passUserToService(data);

        return 
        name: data.displayName,
        avatar: data.photoURL,
        email: data.email,
        provider: data.providerId
        ;

    

    private _getProvider( from: string ) 
        ...STUFF GOING ON HERE...
    

    

TEMPLATE-I-WANT-TO-DISPLAY.TS

    import  Component, OnInit  from '@angular/core';
    import Observable from 'rxjs/Observable';
    import  AdInterface from '../interfaces';
    import  Router  from '@angular/router';
    import  UserdataService      from '../userdata.service';
    import  Subscription    from 'rxjs/Subscription';

    @Component(
    selector: 'app-list-adverts',
    template: `
                <h2 class="timestamp">
                 announced?.uid 
                 announced?.displayName 
                 announced?.photoURL 
                 announced?.email       
                 announced?.providerId                                                         
                </h2>
    `
    )

    export class ListAdvertsComponent implements OnInit 

        subscription: any;
        announced: string;
        userServ: any;

        constructor( private router: Router, private shareUser: UserdataService )  
                        this.userServ = this.shareUser.userDataAvailable$;
                        this.subscription = this.userServ.subscribe(userdata => 
                            this.announced = userdata;
                            // console.log( JSON.stringify(this.announced) );
                        );
                    


        ngOnInit() 
        

        ngOnDestroy() 
            // prevent memory leak when component destroyed
            this.subscription.unsubscribe();
        

    

【问题讨论】:

【参考方案1】:

Angular 有一个完美的依赖注入系统,它可能有助于解决你的问题。

我假设您在应用程序的某些功能模块中提供 UserdataService。尝试在 AppModule 上提供它:

import  UserdataServce  from './path/to/service.ts';

@NgModule(
    imports: [...],
    declarations: [...],
    providers: [
        ...
        UserdataService,
        ...
    ],
    bootstrap: [...]
)
export class AppModule 

这样您可以确保您的组件现在可以获取相同的 UserdataService 实例。

【讨论】:

以上是关于Angular2 - 不同级别的组件之间的持久服务的主要内容,如果未能解决你的问题,请参考以下文章

Angular2 模块级样式表

Angular2:通过引用传递组件之间的交互

如何在多个 Angular 2 项目之间共享一个 Angular 2 组件?

Angular2路由-路由更改时保持组件状态[重复]

如何在Angular2中的组件之间共享数据[重复]

使用 Typescript 在 Angular 2 中的组件之间共享行为