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 { 
} 

注意,這實際上並沒有完成傳播。但它每次都會爲您提供一個新的來源主題。