使用angular2更新服务中组件的可变变化

updating variable changes in components from a service with angular2

本文关键字:变化 组件 angular2 更新 服务 使用      更新时间:2023-09-26

我的应用程序有一个保存名称的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) {
  }
}

在服务中提供事件并在组件中订阅:

@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-组件交互-父母和孩子通过服务进行通信

由于NameService中的name是基元类型,因此您将在服务和组件中获得不同的实例。在NameService中更改name时,组件属性仍然具有初始值,绑定无法按预期工作。

您应该在此处应用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;
  }
}

我认为Günter提供的解决方案是最好的。

也就是说,您必须知道Angular2服务是发生在注入器树中的单例服务。这意味着:

  • 如果您在应用程序级别定义服务(在bootstrap方法的第二个参数中),则实例可以由所有元素(组件和服务)共享
  • 如果在组件级别(在providers属性内)定义服务,则实例将特定于组件及其子组件

有关这方面的更多详细信息,您可以查看"层次依赖注入"文档:https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html

希望它能帮助你,Thierry