Vue2 与 Vue3 路由钩子的区别及用法详解
Vue2 与 Vue3 路由钩子的区别及用法详解
一、核心区别概览
特性 | Vue2 (选项式API) | Vue3 (组合式API) |
---|---|---|
定义方式 | 组件选项形式 | 在setup()中调用函数形式 |
钩子名称 | beforeRouteEnter/Update/Leave | onBeforeRouteUpdate/Leave |
this访问 | beforeRouteEnter不能访问this | 无this概念,直接使用变量 |
异步处理 | next回调处理 | 支持async/await |
组合使用 | 难以复用 | 可轻松组合复用 |
二、Vue2 路由钩子详解
1. 三种组件内守卫
export default {// 1.进入路由前调用(不能访问this)beforeRouteEnter(to, from, next) {next(vm => {// 通过vm访问组件实例})},// 2.路由变化但组件复用时调用beforeRouteUpdate(to, from, next) {// 可以访问thisif (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守卫
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. 重大变化
-
更简单的API:
- 移除了next函数(除非需要重定向)
- 返回
false
取消导航,返回true
或undefined
继续导航 - 可以返回路由路径字符串或对象进行重定向
-
更好的TypeScript支持
-
组合复用示例:
// 可复用的路由守卫逻辑
function useRouteLeaveGuard(unsavedChanges) {onBeforeRouteLeave(() => {if (unsavedChanges.value) {return confirm('确定离开?')}})
}// 组件中使用
setup() {const unsaved = ref(false)useRouteLeaveGuard(unsaved)// ...
}
四、迁移指南
从Vue2到Vue3的转换示例
Vue2版本:
beforeRouteLeave(to, from, next) {if (this.unsavedChanges) {next(confirm('离开吗?'))} else {next()}
}
Vue3版本:
setup() {const unsavedChanges = ref(false)onBeforeRouteLeave(() => {if (unsavedChanges.value) {return confirm('离开吗?')}})
}
注意事项
-
beforeRouteEnter
在Vue3中没有直接对应物,需要改用其他方式:// 替代方案:使用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)}) }
-
全局守卫(beforeEach等)在Vue3中用法保持不变
五、最佳实践建议
-
Vue3推荐模式:
- 优先使用组合式函数封装可复用的路由逻辑
- 利用async/await处理异步操作
- 对于简单逻辑,直接返回布尔值而非使用next
-
复杂场景处理:
// 需要重定向的复杂场景
onBeforeRouteLeave((to, from) => {if (needRedirect) {return { path: '/login', query: { from: to.fullPath } }}if (unsavedChanges.value) {return confirm('确定离开?')}
})
- 组合多个守卫:
setup() {// 可以注册多个同类型守卫onBeforeRouteLeave(checkUnsavedChanges)onBeforeRouteLeave(logRouteChange)onBeforeRouteLeave(analyticsTracker)
}