局部路由守卫
局部路由守卫为我们提供了更细粒度的路由控制,允许我们在特定的路由或组件级别添加鉴权和逻辑处理。局部路由守卫分为 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
守卫,我们可以实现更灵活和安全的路由控制。
编辑
分享
在全局后置守卫中更新页面标题的具体步骤是什么?
如何在全局后置守卫中记录用户访问路径?
除了更新标题栏和记录路径,全局后置守卫还能实现哪些功能?