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
updating variable changes in components from a service with angular2
提问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
回答by hansmaad
Since name
in NameService
is a primitive type, you'll get different instance in the service and your components. When you change name
in NameService
, the component properties still have the initial value and the binding doesn't work as expected.
由于name
inNameService
是原始类型,您将在服务和组件中获得不同的实例。当您name
在 中更改时NameService
,组件属性仍具有初始值,并且绑定无法按预期工作。
You should apply the angular1 "dot rule" here and bind to a reference type. Change NameService
to 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 name
property 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
bootstrap
method), the instance can be share by all elements (components and service). - if you define your service at the component level (within the
providers
attribute), 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
希望对你有帮助,蒂埃里