在加入考試系統項目後,首先作的工做是添加操做提示框,本覺得簡單的工做,在使用時卻出現了使人意想不到的錯誤。html
使用的模態框庫爲sweetalert2
,設計方法是在應用的根組件appComPonent
中使用模態框組件,appComPonent中暴露展現確認模態框的方法confirm,子組件經過注入appComPonent並調用confirm方法,經過傳入回調函數,實如今子組件中展現模態框的功能。app
// app.component.html <swal #alert></swal> <router-outlet></router-outlet> // app.component.ts 中顯示確認框的方法 @ViewChild('alert', {static: true}) public alert: SwalComponent; confirm(callback?: () => void, description: string = '', title: string = '是否確認'): void { /** * 更新提示框信息 */ this.alert.update({ titleText: title, text: description, icon: 'question', background: '#F7F8FA', allowOutsideClick: false, confirmButtonText: '肯定', confirmButtonColor: '#007BFF', showCancelButton: true, cancelButtonText: '取消' }); const result = this.alert.confirm.subscribe(() => { // 執行回調 if (callback) { callback(); } // 取消訂閱 result.unsubscribe(); }); /** * 顯示提示框 */ this.alert.fire(); }
經過訂閱模態框確認數據源(alert.confirm)來保證點擊確認按鈕時執行成功的回調函數。例如在子組件中使用示例:ide
// main.component.ts constructor(private app: AppComponent, private collegeService: CollegeService) { } delete(college: College): void { // 確認框 this.app.confirm(() => { this.collegeService.delete(college.id).subscribe(() => { this.pageAll(); // 操做成功提示 this.app.success(() => {}, `成功刪除${college.name}`); }, () => { // 操做失敗提示 this.app.error(() => {}, '可能存在關聯數據'); }); }, `即將刪除學院信息:${college.name}`); }
本着測試的原則,當按照以前的代碼加入模態框,本身測試瞭如下,卻出現了意想不到的事情:我點擊刪除,以後取消,進入編輯界面保存編輯後,回到首頁卻把數據給刪除了。
函數
回到代碼,當咱們展示刪除提示框時,預定了模態框的確認(alert.confirm)數據源,來保證點擊肯定按鈕時實現刪除的操做,可是我卻沒點擊肯定,點擊的是取消。此時確認數據源還在被咱們預定着,在編輯頁面點擊了保存模態框的肯定按鈕後,因爲使用的是都是根組件中的模態框實例,確認數據源被觸發,從而執行咱們以前預定的刪除操做!測試
解決方法1:
觸發這奇怪現象的源頭就是上一次預定確認數據源沒有取消掉,把這個預定給取消掉,保證每一次模態框關閉後都沒有觀察者在訂閱模態框便可。this
// app.component.ts confirm 方法 const result = this.alert.confirm.pipe(first()).subscribe(() => { // 執行回調 if (callback) { callback(); } // 取消訂閱 cancel.unsubscribe(); }); const cancel = this.alert.cancel.pipe(first()).subscribe(() => { result.unsubscribe(); });
訂閱模態框的確認(confirm)和取消(cancel)事件源,在點擊取消時取消掉確認事件的訂閱,在點擊確認時取消掉取消事件的訂閱,並使用first()操做符保證每一個觀察者只能有一次訂閱。spa
解決方法2:
因爲確認和取消是兩個不一樣的數據源,形成了編寫時的觀念錯誤,把確認和取消合併爲模態框關閉的事件源,便可消除此錯誤。
設計
使用merge
操做符將數據源合併,map
操做符將確認數據源改成true
,取消數據源改成false
:code
// app.component.ts confirm 方法 merge(this.alert.confirm.pipe(map(() => true)), this.alert.cancel.pipe(map(() => false))).pipe(first()) .subscribe((is) => { if (is && callback) { callback(); } });