Javascript 使用 angular2 从服务更新组件中的变量更改

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34714462/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:46:18  来源:igfitidea点击:

updating variable changes in components from a service with angular2

javascriptangular

提问by B Hull

My app has a NameService which holds the name.

我的应用程序有一个 NameService 保存名称。

There are two child components of App, Navbar and TheContent which reference this service. Whenever the name changes in the service, i want it to update in both of the other components. How can i do this?

App 有两个子组件 Navbar 和 TheContent 引用此服务。每当服务中的名称更改时,我希望它在其他两个组件中都更新。我怎样才能做到这一点?

import {Component, Injectable} from 'angular2/core'

// Name Service

@Injectable()
class NameService {
  name: any;
  constructor() {
    this.name = "Hyman";
  }
  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) {
  }
}

回答by Günter Z?chbauer

Provide an event in the service and subscribe to it in the components:

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

@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 = "Hyman";
  }
  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();
  }
}

See also
angular.io - COMPONENT INTERACTION - Parent and children communicate via a service

另请参阅
angular.io - COMPONENT INTERACTION - 父母和孩子通过服务进行交流

回答by hansmaad

Since namein NameServiceis a primitive type, you'll get different instance in the service and your components. When you change namein NameService, the component properties still have the initial value and the binding doesn't work as expected.

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

You should apply the angular1 "dot rule" here and bind to a reference type. Change NameServiceto store an object that contains the name.

您应该在此处应用 angular1“点规则”并绑定到引用类型。更改NameService以存储包含名称的对象。

export interface Info {
   name:string;
}

@Injectable()
class NameService {
  info: Info = { name : "Hyman" };
  change(){
    this.info.name = "Jane";
  }
}

You can bind to this object and get updates to the nameproperty automatically.

您可以绑定到此对象并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;
  }
}

回答by Thierry Templier

I think that the solution provided by Günter is the best one.

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

That said, you must be aware that Angular2 services are singleton that take place into a tree of injectors. This means that:

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

  • if you define your service at the application level (within the second parameter of the bootstrapmethod), the instance can be share by all elements (components and service).
  • if you define your service at the component level (within the providersattribute), the instance will be specific to the component and its sub components.
  • 如果您在应用程序级别(在方法的第二个参数内)定义您的服务,则bootstrap该实例可以由所有元素(组件和服务)共享。
  • 如果您在组件级别(在providers属性内)定义服务,则实例将特定于组件及其子组件。

For more details of such aspect, you can have a look at the "Hierarchical Dependency Injection" doc: https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html

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

Hope it helps you, Thierry

希望对你有帮助,蒂埃里