Vue2 与 Vue3 路由钩子的区别及用法详解

Vue2 与 Vue3 路由钩子的区别及用法详解

一、核心区别概览

特性 Vue2 (选项式API) Vue3 (组合式API)
定义方式 组件选项形式 在setup()中调用函数形式
钩子名称 beforeRouteEnter/Update/Leave onBeforeRouteUpdate/Leave
this访问 beforeRouteEnter不能访问this 无this概念,直接使用变量
异步处理 next回调处理 支持async/await
组合使用 难以复用 可轻松组合复用

二、Vue2 路由钩子详解

1. 三种组件内守卫

javascript 复制代码
export default {
  // 1.进入路由前调用(不能访问this)
  beforeRouteEnter(to, from, next) {
    next(vm => {
      // 通过vm访问组件实例
    })
  },
  
  // 2.路由变化但组件复用时调用
  beforeRouteUpdate(to, from, next) {
    // 可以访问this
    if (to.params.id !== this.$route.params.id) {
      this.fetchData()
    }
    next()
  },
  
  // 3.离开路由前调用
  beforeRouteLeave(to, from, next) {
    if (this.unsavedChanges) {
      if (confirm('有未保存的更改!')) {
        next()
      } else {
        next(false)
      }
    } else {
      next()
    }
  }
}

2. 特点

  • beforeRouteEnter 是唯一不能访问this的守卫
  • 必须调用next()来解析钩子
  • 全局守卫(beforeEach等)仍可用

三、Vue3 路由钩子详解

1. 组合式API守卫

javascript 复制代码
import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'

export default {
  setup() {
    const unsavedChanges = ref(false)
    
    // 1.路由更新守卫
    onBeforeRouteUpdate(async (to, from) => {
      // 不需要next参数(除非需要重定向)
      if (to.params.id !== from.params.id) {
        await fetchData(to.params.id)
      }
    })
    
    // 2.路由离开守卫
    onBeforeRouteLeave((to, from) => {
      if (unsavedChanges.value) {
        return confirm('确定要离开吗?')
      }
    })
    
    return { unsavedChanges }
  }
}

2. 重大变化

  1. 更简单的API

    • 移除了next函数(除非需要重定向)
    • 返回false取消导航,返回trueundefined继续导航
    • 可以返回路由路径字符串或对象进行重定向
  2. 更好的TypeScript支持

  3. 组合复用示例

javascript 复制代码
// 可复用的路由守卫逻辑
function useRouteLeaveGuard(unsavedChanges) {
  onBeforeRouteLeave(() => {
    if (unsavedChanges.value) {
      return confirm('确定离开?')
    }
  })
}

// 组件中使用
setup() {
  const unsaved = ref(false)
  useRouteLeaveGuard(unsaved)
  // ...
}

四、迁移指南

从Vue2到Vue3的转换示例

Vue2版本

javascript 复制代码
beforeRouteLeave(to, from, next) {
  if (this.unsavedChanges) {
    next(confirm('离开吗?'))
  } else {
    next()
  }
}

Vue3版本

javascript 复制代码
setup() {
  const unsavedChanges = ref(false)
  
  onBeforeRouteLeave(() => {
    if (unsavedChanges.value) {
      return confirm('离开吗?')
    }
  })
}

注意事项

  1. beforeRouteEnter在Vue3中没有直接对应物,需要改用其他方式:

    javascript 复制代码
    // 替代方案:使用onMounted + 路由监听
    setup() {
      const userData = ref(null)
      
      onMounted(async () => {
        userData.value = await fetchUser(route.params.id)
      })
      
      watch(
        () => route.params.id,
        async (newId) => {
          userData.value = await fetchUser(newId)
        }
      )
    }
  2. 全局守卫(beforeEach等)在Vue3中用法保持不变

五、最佳实践建议

  1. Vue3推荐模式

    • 优先使用组合式函数封装可复用的路由逻辑
    • 利用async/await处理异步操作
    • 对于简单逻辑,直接返回布尔值而非使用next
  2. 复杂场景处理

javascript 复制代码
// 需要重定向的复杂场景
onBeforeRouteLeave((to, from) => {
  if (needRedirect) {
    return { path: '/login', query: { from: to.fullPath } }
  }
  if (unsavedChanges.value) {
    return confirm('确定离开?')
  }
})
  1. 组合多个守卫
javascript 复制代码
setup() {
  // 可以注册多个同类型守卫
  onBeforeRouteLeave(checkUnsavedChanges)
  onBeforeRouteLeave(logRouteChange)
  onBeforeRouteLeave(analyticsTracker)
}
相关推荐
独隅21 分钟前
在 Lua 中,你可以使用 `os.date()` 函数轻松地将时间戳转换为格式化的时间字符串
开发语言·lua
谷歌开发者42 分钟前
Web 开发指向标 | Chrome 开发者工具学习资源 (六)
前端·chrome·学习
一晌小贪欢1 小时前
【Html模板】电商运营可视化大屏模板 Excel存储 + 一键导出(已上线-可预览)
前端·数据分析·html·excel·数据看板·电商大屏·大屏看板
发现你走远了1 小时前
连接模拟器网页进行h5的调试(使用Chrome远程调试(推荐)) 保姆级图文
前端·chrome
思麟呀1 小时前
Linux的基础IO流
linux·运维·服务器·开发语言·c++
星释1 小时前
Rust 练习册 :Pythagorean Triplet与数学算法
开发语言·算法·rust
星释1 小时前
Rust 练习册 :Nth Prime与素数算法
开发语言·算法·rust
lkbhua莱克瓦242 小时前
Java基础——集合进阶3
java·开发语言·笔记
街尾杂货店&2 小时前
css - 实现三角形 div 容器,用css画一个三角形(提供示例源码)简单粗暴几行代码搞定!
前端·css
顺凡2 小时前
删一个却少俩:Antd Tag 多节点同时消失的原因
前端·javascript·面试