You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

结合modal与emit函数使用时beforeRouteLeave无法立即生效问题

根因分析

该问题是逻辑执行时序导致的:

  1. 首次触发路由跳转时,beforeRouteLeave钩子会同步执行,此时this.isConfirm为false,你主动中断了本次跳转并弹出modal,本次路由请求已经被销毁
  2. 点击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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 02:39:03