Fra*_*sco 4 inheritance angular rxjs6
在我们的应用程序中,我们有一些从BaseComponent.
基础组件实现OnDestroy接口并发出一个 Subject 以通知子级取消订阅最终打开的流。
这是一种可以接受的方法还是每个组件都应该有自己的ngOnDestroy实现?从这篇文章我读到生命周期钩子不是继承的。
基础组件
export abstract class ComponentBase implements OnDestroy {
protected destroy$ = new Subject<boolean>();
ngOnDestroy() {
this.destroy$.next(true);
}
}
Run Code Online (Sandbox Code Playgroud)
子组件
export class ChildComponent extends ComponentBase implements OnInit {
ngOnInit() {
this.service
.getById(userId)
.pipe(takeUntil(this.destroy$)) // this is emitted by the parent
.subscribe(user => { ...}
}
}
Run Code Online (Sandbox Code Playgroud)
2020 年 9 月 9 日更新:
我们在工作中发布了一个库,可以安全地与 Ivy 一起使用,并让您可以将所有组件生命周期作为可观察对象访问:https : //github.com/cloudnc/ngx-observable-lifecycle
也就是说,应该在 Angular 本身的上游修复这个问题的 PR 最近已经合并并发布了(不记得发布了,但看看吧!)
2020 年 5 月 18 日更新:
以下内容不再适用于 Ivy,如下所述:https : //github.com/angular/angular/issues/36776
这里有一个 PR 可以恢复这种行为:https : //github.com/angular/angular/pull/35464
即使它不那么灵活,同时你可以使用这个:https : //github.com/ngneat/until-destroy
如果您使用的是ComponentBaseto 只能让您访问,destroy$我会说这有点矫枉过正。您可能需要扩展另一个类,而 Typescript 不支持多重继承,因此除非确实有必要,否则请尽量避免这种情况。
也就是说,如果您只是在寻找一种以反应方式轻松取消订阅的方法,请查看以下内容:
/**
* Easily unsubscribe from an observable stream by appending `takeUntilDestroyed(this)` to the observable pipe.
* If the component already has a `ngOnDestroy` method defined, it will call this first.
* Note that the component *must* implement OnDestroy for this to work (the typings will enforce this anyway)
*/
export function takeUntilDestroyed<T>(component: OnDestroy): (source: Observable<T>) => Observable<T> {
return (source: Observable<T>): Observable<T> => {
const onDestroy = new Subject();
const previousOnDestroy = component.ngOnDestroy;
component.ngOnDestroy = () => {
if (previousOnDestroy) {
previousOnDestroy.apply(component);
}
onDestroy.next();
onDestroy.complete();
};
return source.pipe(takeUntil(onDestroy));
};
}
Run Code Online (Sandbox Code Playgroud)
然后从你的组件中做 this.myObs$.pipe(takeUntilDestroyed(this))
您也可以在此 PR 中找到该功能和演示用法:https :
//github.com/cloudnc/ngx-sub-form/pull/41/files#diff-5796510f30fdd5bede9d709ce53ef225R45
这是一种可以接受的方法还是每个组件都应该有自己的 ngOnDestroy 实现?
可接受只是一个意见问题,但我强烈反对这种方法,原因如下。
@Component({...})
export class MyComponent extends BaseComponent implements OnDestroy {
public ngOnDestroy() {
// do work
}
}
export class BaseComponent implements OnDestroy {
public ngOnDestroy() {
// never executed
}
}
Run Code Online (Sandbox Code Playgroud)
上面的例子没有发出关于super方法永远不会执行的TypeScript 警告,所以我很想把它称为反模式。
此外,将来你会很想添加额外的生命周期钩子,比如OnInit基类。为此,您必须搜索所有后代以确保它们调用super.ngOnInit().
虽然看起来工作量更大,但使用封装更安全。
export class BaseComponent implements OnDestroy {
public ngOnDestroy() {
// do work
}
}
@Component({...})
export class MyComponent implements OnDestroy {
private readonly _base: BaseComponent = new BaseComponent();
public ngOnDestroy() {
this._base.ngOnDestroy();
}
}
Run Code Online (Sandbox Code Playgroud)
网上有很多关于封装与继承之间优缺点的文章。这实际上是计算机科学中一个冗长的讨论,一些编程语言不支持继承,特别是因为这些问题。我想我是想说这是一个广泛的话题,是你个人选择的问题,但这也是你问这个问题的部分原因。
https://www.developer.com/design/article.php/3525076/Encapsulation-vs-Inheritance.htm
| 归档时间: |
|
| 查看次数: |
2111 次 |
| 最近记录: |