每日小记-Vue中onBeforeRouteLeave遇到的问题

811 阅读2分钟

应组长的要求写了一个表单hook来控制表单内的操作

其中就包含了正在编辑的时候不允许路由跳转,即编辑的时候不允许离开当前页面。

我查找了一下文档就使用了组件路由守卫

onBeforeRouteLeave

但是我在使用的时候是使用一个弹窗来进行提示的

官网的按理就是一个很简单的返回true/false

onBeforeRouteLeave((to)=>{
  if(alert){
    return true
  }else{
    return false
  }
})

true表示允许跳转 false表示不允许

但是这是最基本的使用方式,真实的业务场景会更加的复杂一些

比如我目前的就是要求加了一个弹窗进行操作

onBeforeRouteLeave(() => {
  if (isCurrentOperatingDocuemntChanged.value) {
    showDialog({
      title: '提示',
      message: '当前变动未保存,离开?',
      cancelButtonText: '留在本页',
      confirmButtonText: '离开',
      closeOnPopstate: false,
      showCancelButton: true
    }).then(() => {
     return true
    }).catch(() => {
    })
  } else {
    return true
  }
})

这个方式确实可以阻止当前页面的路由跳转,但是之后的路由会被影响 最明显的是使用router.back后会白屏

并且只要在onBeforeRouteLeave里面使用异步函数 或者声明async就会白屏 我测试了很久还是这样 网上也有看到说在onBeforeRouteLeave中使用next,但是我使用next就会报错

onBeforeRouteLeave((to,next)=>{
    next()//这里会报错
})

后来同事排查了源码后发现如果在onBeforeRouteLeave使用异步函数 则需要使用next进行跳转 并且onBeforeRouteLeave的属性是导航的。所以回调参数是有三个

onBeforeRouteLeave((to,from,next))
    next()//少了from的形参所以出错了

最后的代码是这样的就可以正常实现功能了

onBeforeRouteLeave(async() => {
    if (isCurrentOperatingDocuemntChanged.value) {
      const isLeave = await confirmIsLeavePageDialog()
      return isLeave
    } else {
      return true
    }
  })
  /**
   * 是否确认离开弹窗
   */
  async function confirmIsLeavePageDialog() {
    try {
      await showDialog({
        title: '提示',
        message: '当前变动未保存,离开?',
        cancelButtonText: '留在本页',
        confirmButtonText: '离开',
        closeOnPopstate: false,
        showCancelButton: true
      })
      return true
    } catch {
      return false
    }
  }

官方给出的案例太简单了,并且没有明确的说明在onBeforeRouteLeave中使用异步的问题,记录一下这个问题~