这个答案基于FlavorScape和mahyar在
这里和
这里提供的答案。
无需外部库的解决方案
避免每个组件都包含主题和其代码的一种方法是使用一个基础组件(已在Angular 10.0.6中测试):
base.component.ts
import { Subject } from "rxjs";
import { Component } from "@angular/core";
@Component({
selector: "app-base-component",
template: ""
})
export class BaseComponent {
public ngDestroyed$ = new Subject();
public onDestroy(): void {
this.ngDestroyed$.next();
}
}
foo.component.ts
@Component({
selector: "app-foo",
templateUrl: "./foo.component.html",
styleUrls: ["./foo.component.scss"]
})
export class FooComponent extends BaseComponent implements OnInit, OnDestroy {
fooList$: Observable<FooModel[]>;
@ViewChild(DataBindingDirective) dataBinding: DataBindingDirective;
public gridData: any[];
public gridView: any[];
public mySelection: string[] = [];
constructor(private readonly store: Store<AppState>) {
super();
}
ngOnDestroy(): void {
this.onDestroy();
}
ngOnInit(): void {
this.store.dispatch(ApplicationFooItemsRequestedAction());
this.fooList$ = this.store.select(selectAllApplicationFooItems);
this.fooList$.pipe(takeUntil(this.ngDestroyed$)).subscribe(ul => {
});
}
}
使用外部库
您可以使用@ngneat/until-destroy库来避免编写自定义代码,并支持其他场景(例如,在服务中)
@Component({
selector: "app-foo",
templateUrl: "./foo.component.html",
styleUrls: ["./foo.component.scss"]
})
export class FooComponent extends BaseComponent implements OnInit, OnDestroy {
ngOnInit(): void {
this.store.dispatch(ApplicationFooItemsRequestedAction());
this.fooList$ = this.store.select(selectAllApplicationFooItems);
this.fooList$.pipe(takeUntil(untilDestroyed(this))).subscribe(ul => {
});
}
}
this.ngDestroyed$.complete()
不会导致 takeUntil 完成订阅。相反,您需要调用.next()
。这样,您就不需要调用 complete 和 unsubscribe 了。 - Dmitriy SnitkoswitchMap
或其他操作符,您会在takeUntil()
之前还是之后添加? - user12207064ngDestroyed$.next()
后,必须调用ngDestroyed$.complete()
,否则将会泄漏该主题。它可能是一个小对象,但它会保持活动状态... 关于顺序:takeUntil
总是最后一个,期望的是shareReply
、multicast
和类似的多播操作符。 - Akxe