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)
}
相关推荐
剪刀石头布啊1 分钟前
生成随机数,Math.random的使用
前端
剪刀石头布啊2 分钟前
css外边距重叠问题
前端
剪刀石头布啊3 分钟前
chrome单页签内存分配上限问题,怎么解决
前端
剪刀石头布啊5 分钟前
css实现一个宽高固定百分比的布局的一个方式
前端
剪刀石头布啊8 分钟前
js数组之快速组、慢数组、密集数组、稀松数组
前端
Ro Jace12 分钟前
计算机专业基础教材
java·开发语言
代码游侠28 分钟前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
mango_mangojuice30 分钟前
Linux学习笔记(make/Makefile)1.23
java·linux·前端·笔记·学习
devmoon37 分钟前
运行时(Runtime)是什么?为什么 Polkadot 的 Runtime 可以被“像搭积木一样”定制
开发语言·区块链·智能合约·polkadot·runtmie
时艰.37 分钟前
Java 并发编程 — 并发容器 + CPU 缓存 + Disruptor
java·开发语言·缓存