我有一个FormControl的组件,订阅它的值改变:
@Component(...)
export class FooComponent implements OnInit, OnDestroy {
fooFormControl: FormControl;
...
ngOnInit() {
this.fooFormControl.valueChanges.subscribe(
() => {...},
() => {},
() => {
// never happens
},
);
}
ngOnDestroy() {
//happens
}
}
但是当组件被销毁时,FormControl元素不会被销毁,并且onComplete回调永远不会发生。
在组件销毁时销毁FormControl元素的正确方法是什么?
答案 0 :(得分:2)
FormControl
observables不应该被完成,尽管如果有一些属于完全回调的逻辑,可以手动完成。
由于valueChanges
是事件发射器并且继承自RxJS Subject
,因此可以取消订阅或完成:
ngOnDestroy() {
this.fooFormControl.valueChanges.complete();
// and/or
this.fooFormControl.valueChanges.unsubscribe();
}
将来EventEmitter
可能不会成为主题。这可能会导致重大变化,但目前它完全依赖于RxJS。
答案 1 :(得分:1)
以下是两个可能对您有所帮助的想法。不确定他们是否是正确的方式"但到目前为止它对我来说效果很好。除此之外,我像往常一样取消订阅ngOnDestroy。
#1通过takeUntil
引入您自己的主题强制完成在TypeScript中,valueChanges属性的类型为Observable。如果您不想解决这个问题并进入主题,那么您可以使用takeUntil运算符来介绍您自己的主题。这将允许您强制完成传播,使其高于valueChanges observable。重要的是不要将takeUntil运算符放在switchmap之前,否则切换到observable将继续,并且您的订阅将不会被取消!出于这个原因,我把它放在订阅运算符之前。
以下是一个例子:
const stop = new Subject();
// simulate ngOnDestroy
window.setTimeout(() => {
stop.next();
stop.complete();
}, 3500);
Observable
.interval(1000)
.takeUntil(stop)
.subscribe(
() => { console.log('next'); },
() => { console.log('error'); },
() => { console.log('complete'); }
);
以下是一个工作示例:https://rxviz.com/v/RoQNBnOM
#2将FormBuilder添加到您组件的提供商列表
这就是我通常做的事情。实际上我通常将我的表单封装在使用FormBuilder的服务中,但效果是一样的。在此级别提供服务将在每次创建组件时销毁并重新创建服务。我开始这样做是因为我一直有由可观察流引起的奇怪错误,这些错误是由持续超过组件生命周期的valueChanges创建的。他们会在重新创建组件时重新订阅,以及类似的东西。
以下是一个例子:
@Component({
selector: 'my-form',
templateUrl: './my-form.component.html',
styleUrls: ['./my-form.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [ FormBuilder ] // <-- THIS PART
})
export class MyFormComponent implements OnInit, OnDestroy {
}
请注意,这并未实际传播完成。但它确实每次给你一个新的来源主题。
答案 2 :(得分:0)
您无法破坏表单控件。组件内的所有内容都将随之被破坏,但事件可以保存在您的应用中。所以你可以取消订阅它的活动。
@Component(...)
export class FooComponent implements OnInit, OnDestroy {
fooFormControl: FormControl;
var subscriber;
...
ngOnInit() {
this.subscriber = this.fooFormControl.valueChanges.subscribe(
() => {...},
() => {},
() => {
// never happens
},
);
}
ngOnDestroy() {
this.subscriber.unsubscribe();
}
}