在加入考试系统项目后,首先作的工做是添加操做提示框,本觉得简单的工做,在使用时却出现了使人意想不到的错误。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(); } });