问题描述
我知道这是在SO和互联网上发布的,但是我读了很多不同的东西,现在我有点困惑了。
2个问题-
- 订阅我的组件,constructor()或NgOnInit()的最佳位置是哪里?
- 订阅Observable时应该使用管道,以便Angular可以销毁它,或者我不必使用ngondestroy?订阅后为何会有管道有些困惑?
这是我的一项服务的示例,其中在我的导航栏组件中,我订阅了来自服务的窗口大小更改。
this.responsiveService.getMobileStatus()
.subscribe(mobileStatus => {
this.isMobile = mobileStatus.status;
if (mobileStatus.width < 568) {
this.inputPlaceholder = this.placeholderWithSearch;
} else {
this.inputPlaceholder = this.placeholderWithoutSearch;
}
});
解决方法
-
使用
ngOnInit
进行订阅是一个好习惯,因为@Input
绑定直到此生命周期钩子才被初始化,因此它们尚未在构造函数中准备好,并且通常可观察对象可以依赖于这些绑定价值观。即使他们不同意,保持一致并且始终在同一位置也是一种很好的做法。 -
您应尽可能使用
async
管道来避免手动订阅管理,但这并不总是可行或合理的。
我会说最好使用async
管道,并让angular处理取消订阅。它产生更干净的代码;
让我们考虑订阅在构造函数中的代码
export class MyClassComponent implements OnInit,OnDestroy {
sub: any;
componentName: any;
constructor(private navbarService: NavbarService) {
}
ngOnInit() {
this.sub = this.navbarService.getComponentNameObv()
.subscribe(componentName => {
this.componentName = componentName;
});
}
ngOnDestroy() {
this.sub.unsubscribe()
}
}
使用async
管道我们可以重构
export class MyClassComponent {
componentName$ = this.navbarService.getComponentNameObv();
mobileStatus$ = this.responsiveService.getMobileStatus().pipe(
tap(mobileStatus => {
this.isMobile = mobileStatus.status;
if (mobileStatus.width < 568) {
this.inputPlaceholder = this.placeholderWithSearch;
} else {
this.inputPlaceholder = this.placeholderWithoutSearch;
}
})
)
constructor(private navbarService: NavbarService) {
}
}
代码短得多,也更容易测试