各位观众老爷,大家好!我是你们的老朋友,今天咱们来聊聊Vue 3里边Router的那些导航守卫,特别是 beforeEach
、beforeEnter
这些家伙的执行顺序。这玩意儿啊,看似简单,但真要搞不清楚,就像走迷宫一样,绕来绕去,最后都不知道自己在哪儿了。
今天咱们就来拨开云雾见青天,把这些守卫的执行顺序给它安排得明明白白,让你的代码跑得顺顺溜溜!
开场白:导航守卫,路由界的保安
首先,咱们得明白导航守卫是个啥玩意儿。你可以把它们想象成路由界的保安,每当你想要进入某个页面之前,这些保安都要先盘问一番,看看你有没有通行证,或者有没有什么不良企图,只有通过了它们的检查,你才能顺利进入目标页面。
Vue Router 提供了几种不同的导航守卫,包括:
- 全局守卫:
beforeEach
、afterEach
、beforeResolve
- 路由独享守卫:
beforeEnter
- 组件内的守卫:
beforeRouteEnter
、beforeRouteUpdate
、beforeRouteLeave
今天咱们重点关注 beforeEach
和 beforeEnter
,因为它们是控制路由跳转的关键环节,也是最容易让人感到困惑的地方。
beforeEach
:全局“海关”
beforeEach
是一个全局前置守卫,也就是说,每次路由跳转之前,它都会被执行。你可以把它想象成一个全局的“海关”,所有进出你网站的“旅客”(路由)都要经过它的检查。
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{ path: '/', component: () => import('./components/Home.vue') },
{ path: '/about', component: () => import('./components/About.vue'), meta: { requiresAuth: true } },
{ path: '/login', component: () => import('./components/Login.vue') }
];
const router = createRouter({
history: createWebHistory(),
routes
});
router.beforeEach((to, from, next) => {
console.log('beforeEach: 全局路由守卫被触发');
// 模拟用户是否登录
const isLoggedIn = localStorage.getItem('token');
if (to.meta.requiresAuth && !isLoggedIn) {
console.log('beforeEach: 用户未登录,重定向到登录页面');
next('/login');
} else {
console.log('beforeEach: 允许访问');
next();
}
});
export default router;
在这个例子中,beforeEach
检查每个路由是否需要用户登录 (meta.requiresAuth
),如果需要且用户未登录,则会重定向到登录页面。
beforeEnter
:路由独享的“门卫”
beforeEnter
是一个路由独享的守卫,也就是说,它只会在进入特定的路由时被执行。你可以把它想象成某个页面的“门卫”,只有你想进入这个页面的时候,它才会出来盘问你。
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{ path: '/', component: () => import('./components/Home.vue') },
{
path: '/profile',
component: () => import('./components/Profile.vue'),
beforeEnter: (to, from, next) => {
console.log('beforeEnter: Profile页面的路由独享守卫被触发');
// 模拟检查用户权限
const hasPermission = true;
if (hasPermission) {
console.log('beforeEnter: 用户有权限访问Profile页面');
next();
} else {
console.log('beforeEnter: 用户没有权限访问Profile页面,重定向到首页');
next('/');
}
}
},
{ path: '/login', component: () => import('./components/Login.vue') }
];
const router = createRouter({
history: createWebHistory(),
routes
});
router.beforeEach((to, from, next) => {
console.log('beforeEach: 全局路由守卫被触发');
next();
});
export default router;
在这个例子中,beforeEnter
只会在进入 /profile
路由时被执行,它会检查用户是否有权限访问该页面。
执行顺序:谁先谁后,井然有序
重点来了!beforeEach
和 beforeEnter
的执行顺序是怎样的呢?答案是:
beforeEach
(全局前置守卫):最先执行,所有路由跳转都会触发它。beforeEnter
(路由独享守卫):只有在进入特定路由时才会执行,且在beforeEach
之后执行。
为了更好地理解,咱们用一个表格来总结一下:
守卫类型 | 执行时机 | 作用范围 | 执行顺序 |
---|---|---|---|
beforeEach |
每次路由跳转之前 | 全局 | 1 |
beforeEnter |
进入特定路由之前 | 特定路由 | 2 |
实战演练:代码演示与分析
为了更直观地看到执行顺序,咱们来写一段代码,并在控制台输出一些信息:
// App.vue
<template>
<div>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/profile">Profile</router-link> |
<router-link to="/login">Login</router-link>
<router-view />
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
name: 'App'
});
</script>
// components/Home.vue
<template>
<h1>Home Page</h1>
</template>
// components/About.vue
<template>
<h1>About Page</h1>
</template>
// components/Profile.vue
<template>
<h1>Profile Page</h1>
</template>
// components/Login.vue
<template>
<h1>Login Page</h1>
</template>
然后,在 router/index.js
中添加以下代码:
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{ path: '/', component: () => import('../components/Home.vue') },
{ path: '/about', component: () => import('../components/About.vue'), meta: { requiresAuth: true } },
{
path: '/profile',
component: () => import('../components/Profile.vue'),
beforeEnter: (to, from, next) => {
console.log('beforeEnter: Profile页面的路由独享守卫被触发');
next();
}
},
{ path: '/login', component: () => import('../components/Login.vue') }
];
const router = createRouter({
history: createWebHistory(),
routes
});
router.beforeEach((to, from, next) => {
console.log('beforeEach: 全局路由守卫被触发');
next();
});
export default router;
现在,启动你的 Vue 应用,并在浏览器中切换路由,观察控制台的输出。你会发现,每次路由跳转,beforeEach
都会被首先执行,而只有当你点击 /profile
链接时,beforeEnter
才会执行,且在 beforeEach
之后。
深入理解:next()
函数的重要性
在导航守卫中,next()
函数至关重要。它决定了路由是否可以继续跳转。
next()
: 允许路由继续跳转到目标页面。next(false)
: 中断当前的路由跳转。next('/path')
: 重定向到指定的路径。next(error)
: 中断导航,并将错误传递给router.onError()
注册的回调。
如果你忘记调用 next()
函数,或者错误地调用了 next(false)
,你的路由可能就无法正常跳转了。
应用场景:灵活运用,解决实际问题
了解了 beforeEach
和 beforeEnter
的执行顺序,你就可以灵活运用它们来解决实际问题了。
- 权限控制: 使用
beforeEach
检查用户是否已登录,如果未登录,则重定向到登录页面。 - 页面访问统计: 使用
beforeEach
记录用户的访问行为,例如访问时间、来源页面等。 - 动态路由配置: 使用
beforeEnter
根据用户的角色动态加载不同的组件。
注意事项:避免踩坑,确保代码健壮
在使用导航守卫时,还需要注意以下几点:
- 避免死循环: 在
beforeEach
中重定向到当前路由,可能会导致死循环。 - 异步操作: 在
beforeEach
中进行异步操作时,务必确保在操作完成后再调用next()
函数。 - 参数传递: 可以通过
to.params
和to.query
获取路由参数。 - 使用
meta
字段: 可以在路由配置中使用meta
字段来存储一些自定义的信息,例如是否需要登录、页面标题等。
总结:掌握核心,游刃有余
今天咱们深入探讨了 Vue Router 中 beforeEach
和 beforeEnter
的执行顺序。希望通过今天的讲解,你能够对它们有更深刻的理解,并在实际项目中灵活运用,写出更加健壮、高效的代码。
记住,beforeEach
是全局的“海关”,beforeEnter
是路由独享的“门卫”,掌握它们的执行顺序,就能更好地控制你的路由跳转,让你的应用更加安全、可靠。
最后,希望大家在学习 Vue 的道路上越走越远,早日成为一名真正的 Vue 大师!
感谢大家的观看,咱们下期再见!