Обновление переменных изменений в компонентах из сервиса с angular2
Мое приложение имеет NameService, который содержит имя.
Существует два дочерних компонента App, Navbar и TheContent, которые ссылаются на этот сервис. Всякий раз, когда имя меняется в сервисе, я хочу, чтобы оно обновлялось в обоих других компонентах. Как я могу это сделать?
import {Component, Injectable} from 'angular2/core'
// Name Service
@Injectable()
class NameService {
name: any;
constructor() {
this.name = "Jack";
}
change(){
this.name = "Jane";
}
}
// The navbar
@Component({
selector: 'navbar',
template: '<div>This is the navbar, user name is {{name}}.</div>'
})
export class Navbar {
name: any;
constructor(nameService: NameService) {
this.name = nameService.name;
}
}
// The content area
@Component({
selector: 'thecontent',
template: '<div>This is the content area. Hello user {{name}}. <button (click)=changeMyName()>Change the name</button></div>'
})
export class TheContent {
name: any;
constructor(public nameService: NameService) {
this.name = nameService.name;
}
changeMyName() {
this.nameService.change();
console.log(this.nameService.name);
}
}
@Component({
selector: 'app',
providers: [NameService],
directives: [TheContent, Navbar],
template: '<navbar></navbar><thecontent></thecontent>'
})
export class App {
constructor(public nameService: NameService) {
}
}
3 ответа
Предоставьте событие в сервисе и подпишитесь на него в компонентах:
@Injectable()
class NameService {
name: any;
// EventEmitter should not be used this way - only for `@Output()`s
//nameChange: EventEmitter<string> = new EventEmitter<string>();
nameChange: Subject<string> = new Subject<string>();
constructor() {
this.name = "Jack";
}
change(){
this.name = 'Jane';
this.nameChange.next(this.name);
}
}
export class SomeComponent {
constructor(private nameService: NameService) {
this.name = nameService.name;
this._subscription = nameService.nameChange.subscribe((value) => {
this.name = value;
});
}
ngOnDestroy() {
//prevent memory leak when component destroyed
this._subscription.unsubscribe();
}
}
Смотрите также
angular.io - ВЗАИМОДЕЙСТВИЕ КОМПОНЕНТОВ - Родитель и дети общаются через сервис
Поскольку name
в NameService
это примитивный тип, вы получите разные экземпляры в сервисе и ваших компонентах. Когда вы меняете name
в NameService
свойства компонента по-прежнему имеют начальное значение, и привязка не работает должным образом.
Здесь вы должны применить "правило точки" angular1 и привязать его к ссылочному типу. + Изменить NameService
хранить объект, который содержит имя.
export interface Info {
name:string;
}
@Injectable()
class NameService {
info: Info = { name : "Jack" };
change(){
this.info.name = "Jane";
}
}
Вы можете привязать к этому объекту и получать обновления name
свойство автоматически.
// The navbar
@Component({
selector: 'navbar',
template: '<div>This is the navbar, user name is {{info.name}}.</div>'
})
export class Navbar {
info: Info;
constructor(nameService: NameService) {
this.info = nameService.info;
}
}
Я думаю, что решение, предоставленное Гюнтером, является лучшим.
Тем не менее, вы должны знать, что сервисы Angular2 являются одноэлементными и размещаются в дереве инжекторов. Это означает, что:
- если вы определяете свой сервис на уровне приложения (в рамках второго параметра
bootstrap
метод), экземпляр может совместно использоваться всеми элементами (компонентами и службой). - если вы определяете свой сервис на уровне компонентов (в пределах
providers
атрибут), экземпляр будет специфичным для компонента и его подкомпонентов.
Для получения более подробной информации о таком аспекте, вы можете взглянуть на документ "Внедрение иерархической зависимости": https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html
Надеюсь, это поможет тебе, Тьерри