我的目标原则上很简单,但我不能把它放到位:我希望在更改服务变量时更新我的一个组件。
为了更好地解释我的问题,这里有一个例子:
在这里,我有一项服务可以增加或减少一些积分。当它接收到对其某个功能的调用时,它会减少或增加这个点数。它还说这个变量是偶数还是奇数
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class TestService {
Number: number = 0;
IsOdd: boolean = false;
constructor() {}
IncreaseNumber() {
this.Number = this.Number + 1;
this.IsOdd = !this.IsOdd;
}
DecreaseNumber() {
this.Number = this.Number - 1;
this.IsOdd = !this.IsOdd;
}
}
*在这里,我有我的组件,需要知道我的数字是偶数还是奇数。
初始化时没问题!它知道它!
每次数字在我的服务中更改(test.service.ts)时,我确保我的组件中的值对/导入更改(test.component.ts)?*
import { Component, OnInit } from '@angular/core';
import { TestService } from '../test.service'
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
IsOdd: boolean = false;
constructor(MyService: TestService) {}
ngOnInit() {
this.IsOdd = MyService.IsOdd;
}
}
我该怎么办?
我的组件是否需要subscribe
以某种方式提供给我的服务?或者我是否必须使用像ngOnInit
这样的功能但是要更新?
提前致谢
如果这些服务变量属于像Object或Array这样的复杂类型,它会自动更新,因为它们是引用类型。但由于您具有类型编号和布尔值的服务变量,因此它们不会自动更新,因为它们是基本类型,因此通过值传递。
所以你必须使用BehaviorSubject
s并将它们暴露给asObservable
s。您将通过调用BehaviorSubject
方法更新这些next
s的值。这是如何做:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class TestService {
private myNumberValue = 0;
private isOddValue = false;
private myNumber: BehaviorSubject<number> = new BehaviorSubject<number>(this.myNumberValue);
private isOdd: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
myNumber$: Observable<number> = this.myNumber.asObservable();
isOdd$: Observable<boolean> = this.isOdd.asObservable();
constructor() {}
increaseNumber() {
this.myNumberValue = this.myNumberValue + 1;
this.myNumber.next(this.myNumberValue);
this.isOddValue = !this.isOddValue;
this.isOdd.next(this.isOddValue);
}
decreaseNumber() {
this.myNumberValue = this.myNumberValue - 1;
this.myNumber.next(this.myNumberValue);
this.isOddValue = !this.isOddValue;
this.isOdd.next(this.isOddValue);
}
}
现在在你的组件中,你需要做的就是subscribe
到服务中的public
ly暴露的Observable
值:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { TestService } from '../test.service'
import { Subscription } from 'rxjs';
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit, OnDestroy {
isOdd: boolean;
subscription: Subscription;
constructor(private testService: TestService) {}
ngOnInit() {
this.subscription = this.testService.isOdd$.subscribe(isOdd => this.isOdd = isOdd);
}
ngOnDestroy() {
this.subscription && this.subscription.unsubscribe();
}
}
现在,因为你在subscribe
中有isOdd$
d到ngOnInit
,它在组件初始化期间被调用,所以每次在服务中的isOdd
发生变化时,你的Component上的isOddValue
都会更新。
此外,由于这是一个自定义subscription
,它应该被分配给组件(subscription
)中的属性,该属性类型为Subscription
,这是我们从subscribe
方法获得的返回值。我们将不得不在unsubscribe
上调用ngOnDestroy
来避免内存泄漏。
PS:根据Angular's Styleguide,Angular Classes中的属性和方法名称应该在lowerCamelCase中。
使用较低的驼峰案例来命名属性和方法。
对于你要说的工作,你应该在TestComponent中增加/减少服务中的number
,而不是在其他组件中。
import { Component, OnInit } from '@angular/core';
import { TestService } from '../test.service'
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
IsOdd: boolean = false;
constructor(MyService: TestService) {}
ngOnInit() {
this.IsOdd = MyService.IsOdd;
}
increase() {
MyService.IncreaseNumber();
}
decrease() {
MyService.DecreaseNumber();
}
getIsOdd() {
return MyService.IsOdd;
}
}
您可以使用多种解决方案,包括设置Observable以订阅更改。这些都是有效的解决方案。
最简单的解决方案是绑定到模板中的服务而不是值:
<div> {{ MyService.IsOdd }} </div>
在ngOnInit
中,您将布尔值赋给组件上的属性。该值永远不会改变。为了创建数据绑定并响应更改,您必须使用需要.
的对象绑定对属性的引用。因此,MyService.IsOdd
将在模板中工作。
可观察是一种很好的方法。
另一个简单的方法,在我看来更简单的是每当在IncreaseNumber
中调用DecreaseNumber
或TestService
方法时发出一个事件。
然后,在TestComponent
的构造函数中,您可以订阅您在TestService中创建的事件,然后更新您的IsOdd
字段(或您希望在组件中更新的任何其他字段)。此订阅是可能的,因为事件是observable的包装器。
像这样:首先,在您的服务中创建一个事件发射器
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class TestService {
Number: number = 0;
IsOdd: boolean = false;
EmitIsOdd = new EventEmitter<any>();
constructor() {}
IncreaseNumber() {
this.Number = this.Number + 1;
this.IsOdd = !this.IsOdd;
this.EmitIsOdd.emit();
}
DecreaseNumber() {
this.Number = this.Number - 1;
this.IsOdd = !this.IsOdd;
this.EmitIsOdd.emit();
}
}
然后在Component构造函数中订阅该事件
import { Component, OnInit } from '@angular/core';
import { TestService } from '../test.service'
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
IsOdd: boolean = false;
constructor(MyService: TestService) {
this.MyService.EmitIsOdd.subscribe(
() => {
this.IsOdd = this.MyService.IsOdd;
}
);
}
ngOnInit() {
this.IsOdd = MyService.IsOdd;
}
}
你去,简单而有效。