Внедрить экземпляр компонента в службу

По какой-то причине я пытаюсь внедрить свой компонент в службу, но получаю его новый экземпляр. Я воспроизвожу свою проблему с этим кодом:

Этот компонент будет отображать номер экземпляра в h1 :

@Component({
    selector: 'my-component',
    template: '<h1>Instance number {{count}}</h1>'
})
export class MyComponent {
    private static i = 0;               /* <-- counts the myComponent's instances here */
    private _count: number = i++;
    get count(): number {return this._count}
}

Служба зарегистрирует номер экземпляра в консоли:

@Injectable()
export class MyService {
    constructor(myComponent: MyComponent) {
        console.log("Instance number " + myComponent.count);
    }
}

Основной компонент внедрит компонент в представление и службу:

@Component({
    selector: 'app-root',
    template: '<my-component></my-component>',
})
export class AppComponent {
    constructor(service: MyService) {
    }
}

Я использую angular-cli, мой app.module.ts выглядит так:

@NgModule({
  declarations: [
    AppComponent,
    MyComponent
  ],
  imports: [
    BrowserModule,
  ],
  providers: [MyComponent, MyService],
  bootstrap: [AppComponent]
})
export class AppModule { }

В настоящее время моя консоль отображает Instance number 0, а мой HTML-дисплей Instance number 1. Как я могу получить тот же экземпляр?

Спасибо, что читаете меня


person Karbos 538    schedule 01.12.2016    source источник


Ответы (2)


Это не работает. Если в вашем приложении есть несколько экземпляров этого компонента, какой из них следует внедрить.

Что вы можете сделать, так это, например, внедрить службу в компонент и заставить компонент передать себя службе.

@Component({
    selector: 'my-component',
    template: '<h1>Instance number {{count}}</h1>'
})
export class MyComponent {

    constructor(service: MyService) {
      service.myComponent = this;
    }

    private static i = 0;
    private _count: number = i++;
    get count(): number {return this._count}
}

Лучше не передавать компоненты службам, а вместо этого использовать наблюдаемые объекты для уведомления компонентов о событиях и позволить компонентам делать все остальное.

Дополнительные сведения см. на странице https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

person Günter Zöchbauer    schedule 01.12.2016
comment
Почему лучше? Когда вы передаете компоненты сервисам, по крайней мере, через несколько месяцев вы все еще понимаете, что делал ваш код. - person Qian Chen; 24.11.2019
comment
@QianChen Философия Angular заключается в том, что вы манипулируете состоянием, а представление (компоненты Angular) просто отображает это состояние, чтобы поддерживать чистые зависимости только в одном направлении. Если вы передаете компоненты таким образом, вы делаете компоненты частью состояния. В долгосрочной перспективе это приведет к беспорядку. Если вы все равно не следуете этой философии Angular, то передача компонентов службе не будет иметь большого значения. - person Günter Zöchbauer; 24.11.2019
comment
Я понимаю, что вы сказали. На практике я обнаружил, что беспорядок создают наблюдаемые. - person Qian Chen; 24.11.2019

Спасибо за ваш ответ @Günter. Я публикую свой новый компонент с подпиской на сервис здесь для всех, кто интересуется:

Наблюдаемый сервис:

@Injectable()
export class MyService implements OnDestroy {
    private _count:number = 0;
    public numberSource = new Subject<number>();
    private numberObservable: Observable<number> = this.numberSource.asObservable().share();

    public count() {this.numberSource.next(this._count++);}
    public subscribe(s: any) {return this.numberObservable.subscribe(s);}
    public ngOnDestroy() {this.numberSource.complete();}
}

Компонент подписчика (у меня может быть много):

@Component({
    selector: 'my-component',
    template: `
<button (click)="increment()" >Count !</button>
<div *ngFor="let n of numbers">{{n}}</div>
`
})
export class MyComponent {
    private numbers: number[] = [];
    constructor(private myService: MyService) {
        myService.subscribe((n:number) => this.numbers.push(n));
    }
    increment() {
        this.myService.count();
    }
}

Я не знаю, понятно ли я, но это именно то, что я искал. Спасибо !

person Karbos 538    schedule 01.12.2016
comment
Вы получили на него ответ? - person Nasrul Bharathi; 05.06.2018