Angular 将属性公开为可观察属性的最简单语法?

Angular 将属性公开为可观察属性的最简单语法?,angular,typescript,angular-observable,Angular,Typescript,Angular Observable,我已经看过很多教程,展示了无数种不同的方法来实现角度观测。就我的目的而言,其中许多似乎过于复杂。其他版本适用于以前的版本,不再适用 假设我有一个名为numChickens的单一属性的服务,我希望允许组件订阅该属性。真的((需要)=>to.chain((a)=>{million.garbledyGook().statements.to('gether)})让它工作吗 以下是有关服务的代码: import { Injectable } from '@angular/core'; @Injectab

我已经看过很多教程,展示了无数种不同的方法来实现角度观测。就我的目的而言,其中许多似乎过于复杂。其他版本适用于以前的版本,不再适用

假设我有一个名为
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中的
属性
,以便组件类可以访问该属性的值作为可观察流?或者组件模板可以使用异步管道显示该值

我再怎么强调也不为过——请不要回答包含8192个字符的闭包,然后说“看,这很简单”


我问这个问题不仅仅是为了我自己,也是为了像我这样的其他人,他们正试图把他们的脑袋绕到可观测的物体上,并与所有关于这个主题的密集和过时的教程作斗争。如果你能将这个解决方案简化为一个简单的形式,后代将感谢你。

如果你真的想将它作为一个流公开,你所需要做的一切要做的是添加一行:

import { Injectable } from '@angular/core';
import { of } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ChickenService {

  public chickens: number; 
  public chickens$ = of(chickens);
  constructor() { }
}
注意,这样做仍然不允许您更新值,因此这样做没有多少附加值

您可以使用主题来更新值,并通过订阅流在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);
  }
}

注意:我尽量避免在不必要时显式使用主题。

最简单的方法是创建一个私有的
主题,并使用它来创建公共的
可观察的

在下面的代码中,我为您的
checks
变量创建了
get
set
。这意味着每次使用(例如)
service.chicks=10
更新它时,它都会用新值自动触发
可观察的
流上的新事件

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;
  }

}
从'@angular/core'导入{Injectable};
从“rxjs”导入{Subject,observeable};
@注射的({
providedIn:'根'
})
出口级小鸡服务{
private _:number;//将此设置为私有,以便我们可以通过get/set公开它
private chickenChange$=new Subject();//这将用于创建可观察的
公共鸡$=this.chickenChange$.asObservable();//这是我们可以观察到的
构造函数(){}
集鸡(val:数量){
此。_=val;//设置新值
this.chickenChange$.next(val);//触发主题,该主题触发可观察对象
}
养鸡{
把这个还给我;
}
}

你可以考虑使用一个装饰器来把一个属性变成可观察的。这样做的细节并不特别有趣,但是一旦你完成了,你就可以写下类似的东西:

export class ChickenService {
  @Observablize()
  public chickens: number; 

  public chickens$: Observable<number>;
}
导出类ChickenService{
@可观察()
公众鸡只:数目;
公鸡:可见;
}
好的,现在深吸一口气。下面是装饰器实现的大致情况(未经测试)

函数Observalize(){
返回函数(目标,propertyKey:string,描述符:PropertyDescriptor){
const observekey=propertyKey+“$”;
const privateKey=propertyKey+“389;”;
Object.defineProperties(target.prototype{
[ObserveKey]:{value:new Subject()},
[propertyKey]:{
get(){返回此[privateKey];},
set(v){this[privateKey]=v;this[observeKey].next(v);}
}
});
};
}

什么是可观察的()
do,为什么需要它呢?我以为
Subject
s已经是可观察的了。@torazaburo
Subject
s是
可观察的
s,但他们也是
观察者
s。通过
一个可观察的
来公开它,这意味着我们服务之外的任何东西都不能触发该流上的事件。他们可以听,但是他们不会写字吗
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); }
      }
    });
  };
}