2

我有它的价值变动与FormControl组件和订阅:如何销毁组件销毁的反应FormControl?

@Component(...) 
export class FooComponent implements OnInit, OnDestroy { 
    fooFormControl: FormControl; 

    ... 

    ngOnInit() { 
    this.fooFormControl.valueChanges.subscribe(
    () => {...}, 
    () => {}, 
    () => { 
     // never happens 
     }, 
    ); 
    } 

    ngOnDestroy() { 
    //happens 
    } 
} 

但是,当部分已被摧毁FormControl元素不破坏的onComplete回调从未发生过。

什么是正确的方式来销毁组件销毁的FormControl元素?

回答

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(); 
    } 
} 
2

FormControl观测不应该完成,虽然它是可以手动做到这一点,如果有属于完成回调一些逻辑。

由于valueChanges是事件发射器和RxJS Subject继承,它可以退订或完成:

ngOnDestroy() { 
    this.fooFormControl.valueChanges.complete(); 
    // and/or 
    this.fooFormControl.valueChanges.unsubscribe(); 
} 

这可能是EventEmitter不会在未来的主题。这可能会导致重大变化,但目前它完全依赖于RxJS。

1

这里有两个想法可以帮助你。不知道他们是否是“正确的方式”,但迄今为止它对我来说工作得很好。除此之外,我像往常一样在ngOnDestroy中取消订阅。

#1力经由takeUntil

介绍自己的主题在打字稿中valueChanges属性完成的类型是可观察的。如果你不想解决这个问题并且到达主题,那么你可以使用takeUntil操作符来引入你自己的主题。这将允许您强制完成的传播级别高于valueChanges可观察值。在switchmap之前不要使用takeUntil操作符,或者切换到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 { 
} 

注意,这实际上并没有完成传播。但它每次都会为您提供一个新的来源主题。