我看过一些教程,这些教程展示了在Angular中实现可观察对象的多种不同方法。就我的目的而言,其中许多似乎过于复杂。其他版本则适用于以前的版本,不再起作用。
比方说,我有一个带有名为numChickens
的单个属性的服务,并且我希望允许组件订阅该属性。是否真的要(真的需要(=)to.chain((a)=> {million.garbledyGook()。statements.to('gether)})来做到这一点?
这是有关服务的代码:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ChickenService {
public chickens: number;
constructor() { }
}
...这是将使用可观察的组件的代码:
import { Component, OnInit } from '@angular/core';
import { ChickenService } from '../chicken.service';
@Component({
selector: 'app-chickendisplay',
templateUrl: './chickendisplay.component.html',
styleUrls: ['./chickendisplay.component.scss']
})
export class ChickenDisplayComponent implements OnInit {
constructor(public cs: ChickenService) {
}
ngOnInit() {
}
}
在Angular 6中,最简单,最直接,最易读的方法是在ChickenService中公开chickens
属性,以便组件类可以按如下方式访问该属性的值:可观察的流?还是使组件模板可以使用异步管道显示值?
我不能强调那么多-请不要回答,包括一个8192个字符的闭包墙,然后说“看,很简单”。
我不仅向自己问这个问题,还向像我这样的其他人问这个问题,这些人试图将头围在可观察物上,并在有关该主题的所有密集且过时的教程中苦苦挣扎。如果您可以将此解决方案简化为简单的形式,子孙后代将感谢您。
答案 0 :(得分:1)
如果您真的想将其公开显示为流,那么您要做的就是添加一行:
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ChickenService {
public chickens: number;
public chickens$ = of(chickens);
constructor() { }
}
请注意,这样做仍然不允许您更新值,因此这样做没有太多附加值。
您可以使用Subject来订阅流,以更新值并在UI中反映这些更改:
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ChickenService {
public chickens: number;
public chickens$ = chickensSub$.asObservable();
private chickensSub$ = new BehaviorSubject();
constructor() { }
updateChickens(value: number) {
this.chichensSub$.next(value);
}
}
注意:我尽量避免在不必要时明确使用主题。
答案 1 :(得分:1)
最简单的方法是创建一个私有Subject
,并使用它来创建您的公共Observable
。
在下面的代码中,我为您的get
变量创建了set
和chickens
。这意味着每次您使用(例如)service.chickens = 10
更新它时,它将使用新值自动触发Observable
流上的新事件。
import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ChickenService {
private _chickens: number; // Make this private so we can expose it via a get/set
private chickenChange$ = new Subject<number>(); // This will be used to create our Observable
public chickens$ = this.chickenChange$.asObservable(); // This is our Observable
constructor() { }
set chickens(val: number) {
this._chickens = val; // Set the new value
this.chickenChange$.next(val); // Trigger the subject, which triggers the Observable
}
get chickens() {
return this._chickens;
}
}
答案 2 :(得分:1)
您可能会考虑使用装饰器将属性变为可观察的属性。这样做的细节并不是特别有趣,但是一旦完成,您将可以编写如下内容:
export class ChickenService {
@Observablize()
public chickens: number;
public chickens$: Observable<number>;
}
好,现在深吸一口气。装饰器的实现大致如下(未试用)。
function Observablize() {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
const observableKey = propertyKey + "$";
const privateKey = propertyKey + "_";
Object.defineProperties(target.prototype, {
[observableKey]: { value: new Subject<any>() },
[propertyKey]: {
get() { return this[privateKey]; },
set(v) { this[privateKey] = v; this[observableKey].next(v); }
}
});
};
}