结合modal与emit函数使用时beforeRouteLeave无法立即生效问题
根因分析
该问题是逻辑执行时序导致的:
- 首次触发路由跳转时,
beforeRouteLeave钩子会同步执行,此时this.isConfirm为false,你主动中断了本次跳转并弹出modal,本次路由请求已经被销毁 - 点击modal的Yes按钮修改
isConfirm状态后,没有逻辑会自动重新触发之前被中断的路由跳转,只有第二次触发跳转时,beforeRouteLeave检测到isConfirm为true才会放行,就出现了需要点击两次的现象
修复方案
方案1:手动触发路由跳转(实现最简单,推荐)
提前缓存首次跳转的目标路由信息,用户确认后主动调用路由跳转方法:
// 父组件新增变量存储目标路由 data() { return { isConfirm: false, targetRoute: null, showLeaveModal: false } }, beforeRouteLeave(to, from, next) { // 已确认直接放行 if (this.isConfirm) return next() // 缓存目标路由,弹出提示,中断本次跳转 this.targetRoute = to this.showLeaveModal = true next(false) }, methods: { confirm() { this.isConfirm = true // 主动跳转到之前缓存的目标地址 this.$router.push(this.targetRoute) } }
方案2:暂存next回调直接调用(性能更优)
直接把beforeRouteLeave的放行回调存储起来,用户确认后直接调用回调完成跳转,不需要重新触发路由解析:
// 父组件新增变量存储放行回调 data() { return { isConfirm: false, leaveNextCallback: null, showLeaveModal: false } }, beforeRouteLeave(to, from, next) { if (this.isConfirm) return next() // 存储放行回调,弹出提示,中断本次跳转 this.leaveNextCallback = next this.showLeaveModal = true next(false) }, methods: { confirm() { this.isConfirm = true // 调用存储的放行回调完成跳转 if (this.leaveNextCallback) { this.leaveNextCallback() this.leaveNextCallback = null } } }
如果Modal组件封装在子组件中,只需要在emit确认事件时同步传递相关状态即可,核心逻辑不需要调整。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

