局部路由守衛為我們提供了更細粒度的路由控制,允許我們在特定的路由或組件級別添加鑒權和邏輯處理。局部路由守衛分為?path
?守衛和?component
?守衛,它們分別適用于不同的場景。
path
?守衛(路由守衛)
path
?守衛用于在進入特定路由之前執行邏輯處理,如鑒權、數據預加載等。它的書寫位置是在?route
?對象中,通過?beforeEnter
?方法來設置。
javascript
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue';
import Cart from '../views/Cart.vue';
import Profile from '../views/Profile.vue';
import Login from '../views/Login.vue';const routes = [{path: '/',name: 'Home',component: Home},{path: '/cart',name: 'Cart',component: Cart,beforeEnter: (to, from, next) => {const isLoggedIn = localStorage.getItem('isLoggedIn');if (!isLoggedIn) {next({ name: 'Login' });} else {next();}}},{path: '/profile',name: 'Profile',component: Profile,beforeEnter: async (to, from, next) => {const isLoggedIn = localStorage.getItem('isLoggedIn');if (!isLoggedIn) {next({ name: 'Login' });} else {try {// 模擬異步數據預加載const userData = await fetchUserData();to.meta.userData = userData;next();} catch (error) {console.error('數據預加載失敗:', error);next({ name: 'ErrorPage' });}}}},{path: '/login',name: 'Login',component: Login}
];const router = createRouter({history: createWebHistory(),routes
});// 模擬異步獲取用戶數據
function fetchUserData() {return new Promise((resolve, reject) => {setTimeout(() => {const userData = {name: 'John Doe',email: 'johndoe@example.com'};resolve(userData);}, 1000);});
}export default router;
在上述代碼中,我們為?/cart
?和?/profile
?路由添加了?beforeEnter
?守衛。對于?/cart
?路由,我們檢查用戶是否登錄,如果未登錄則跳轉到登錄頁面。對于?/profile
?路由,我們不僅檢查用戶是否登錄,還模擬了異步數據預加載。如果數據預加載失敗,我們將跳轉到錯誤頁面。
component
?守衛(組件守衛)
component
?守衛用于在路由組件進入或離開時執行邏輯處理,如數據清理、確認提示等。它的書寫位置是在路由組件當中,也就是?.vue
?文件里。在?setup
?語法糖中,我們可以使用?onBeforeRouteUpdate
?和?onBeforeRouteLeave
?方法來設置組件守衛。
vue
<template><div><h1>detail組件-{{ id }}</h1><button @click="router.back()">返回</button><hr><h2>猜你喜歡</h2><ol><li @click="goDetailLike">忠犬八公</li></ol></div>
</template><script setup>
import { watch } from 'vue';
import { onBeforeRouteLeave, onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';const route = useRoute();
const router = useRouter();let id = route.query.id;const goDetailLike = () => {router.push({name: 'detail',query: {id: '5566'}});
};onBeforeRouteUpdate((to, from) => {console.log(`根據${to.query.id}請求數據`);// 可以在這里進行數據更新操作fetchData(to.query.id);
});onBeforeRouteLeave(() => {let flag = window.confirm('你確定要離開嗎');if (!flag) return false;// 可以在這里進行數據清理操作clearData();
});// 模擬異步獲取數據
function fetchData(id) {return new Promise((resolve, reject) => {setTimeout(() => {console.log(`獲取到 ${id} 的數據`);resolve();}, 1000);});
}// 模擬數據清理
function clearData() {console.log('清理數據');
}
</script><style scoped></style>
在上述代碼中,onBeforeRouteUpdate
?守衛會在當前路由更新時觸發,我們可以在這里進行數據更新操作。onBeforeRouteLeave
?守衛會在離開當前路由組件前觸發,我們可以在這里進行確認提示和數據清理操作。
局部路由守衛的組合使用
在實際應用中,我們可以組合使用?path
?守衛和?component
?守衛,以實現更復雜的路由控制。例如,我們可以在?path
?守衛中進行全局鑒權,在?component
?守衛中進行組件級別的數據處理和提示。
javascript
// router/index.js
const routes = [{path: '/admin',name: 'Admin',component: Admin,beforeEnter: (to, from, next) => {const isAdmin = localStorage.getItem('isAdmin');if (!isAdmin) {next({ name: 'Forbidden' });} else {next();}}}
];// Admin.vue
<template><div><h1>管理員頁面</h1></div>
</template><script setup>
import { onBeforeRouteLeave } from 'vue-router';onBeforeRouteLeave(() => {let flag = window.confirm('你確定要離開管理員頁面嗎');if (!flag) return false;
});
</script><style scoped></style>
在上述代碼中,我們在?path
?守衛中檢查用戶是否為管理員,如果不是則跳轉到禁止訪問頁面。在?component
?守衛中,我們在離開管理員頁面時進行確認提示。通過組合使用?path
?守衛和?component
?守衛,我們可以實現更靈活和安全的路由控制。
編輯
分享
在全局后置守衛中更新頁面標題的具體步驟是什么?
如何在全局后置守衛中記錄用戶訪問路徑?
除了更新標題欄和記錄路徑,全局后置守衛還能實現哪些功能?