订阅可观察的输入

问题描述 投票:0回答:2

有没有办法订阅

Observable
,这是一个
@Input

例如:

export class MyComponent implements OnInit {
  @Input() results: Observable<string[]>;
  constructor() {
     this.results.subscribe(value => ...);
  }    
}

在这个例子中,我无法订阅可观察的,因为它是

null
...

angular
2个回答
34
投票

编辑:由于角度信号,这个答案现在基本上已经过时了。

我真的不喜欢将

Observable
作为
@Input
本身,但我非常喜欢将标准
@Input()
变成
Observable
。这是一种更加灵活的方法,可以更轻松地在组件和外部之间保持更清晰的边界。一旦您开始订阅从父组件传入的可观察量,您就会带来很多不必要的复杂性。

这是我发现实现这一目标的最佳方法,并且我越来越多地使用 RxJS 并看到了它的威力。这有点笨拙,但我真的希望将来能为类似的事情提供更好的框架支持。

// 'floating' input parameter, with default value of 'false'
@Input('floating') set floating(floating: boolean) { this.floating$.next(floating); };
private floating$ = new BehaviorSubject<boolean>(false);

然后在父组件中你可以传入一个布尔值:

<app-magic-box [floating]="true"></app-magic-box>
<app-magic-box [floating]="shouldFloatMagicBox"></app-magic-box>

如果您发送的内容作为

Observable
存储在“外部”,那么请务必使用异步管道将其发送。这会将这个特定属性的订阅和清理留给父组件(和框架),而不是尝试在魔盒组件内处理它。

<app-magic-box [floating]="float$ | async"></app-magic-box>

在你的魔盒组件中,你现在可以按照你想要的方式使用这个可观察的。请注意,它有默认值

false
,因此如果我们从未设置
floating
,它仍然可以使用。

 public showRabbit$: Observable<boolean>;

 ngOnInit()
 {
     // (only run this initialization once)

     // subscribe directly if you wish, but keep a reference to dispose in ngOnDestroy
     this.floating$.subscribe(floating => ...);

     // we can also create a new observable based on our input parameters
     // with whatever RxJS you want. if a new input value is set it will 
     // propagate through all the pipes

     // show a rabbit when not floating (why not!)
     this.showRabbit$ = this.floating$.pipe(map(floating => floating == false));
 }

现在你的魔术盒中有另一个可观察的东西,你可以在模板中使用它。您会发现“异步”管道在四处传播,但这没关系。

<img *ngIf="showRabbit$ | async" src="./rabbit.png"/>

重要提示:如果您想将其用作

@HostBinding
,您必须执行以下操作:

@HostBinding("attr.floating")
get attr_floating() { return this.floating$.value; }

如果您确实对访问BehaviourSubject 上的

value
有问题,请给我一个更好的解决方案;-) 在我在这里所做的上下文中,我对此没有任何问题。

我真的希望未来框架能够有像

@InputObservable
这样的东西,它可以比我们今天能实现的更神奇地完成类似的事情。

Github 上有一个长期悬而未决的问题 - 但我必须警告你,这不适合胆小的人!


16
投票

您应该实现

OnChanges
并在输入发生变化时订阅它。

export class MyComponent implements OnChanges {
  @Input() results: Observable<string[]>;

  constructor() { }

  ngOnChanges(changes){
      if(changes["results"] && this.results){
          this.results.subscribe(value => ...);
      }
  } 
}

这将允许您在 Observable 可用时订阅它,并在 Observable 引用发生变化时重新订阅它。您可能需要根据您的用例考虑取消订阅旧实例。

© www.soinside.com 2019 - 2024. All rights reserved.