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)
}