深入使用
导航守卫
在路由跳转前、跳转后或解析过程中,我们往往需要插入自定义逻辑,比如权限验证或页面埋点。理解 to(目标路由)、from(当前离开的路由)和 next(控制函数)是掌握守卫的关键。
- next():继续执行路由。
- next(false):中断当前导航,如果浏览器 URL 已改变,则回退到
from路由。 - next('/path'):跳转到指定路径。
- next(error):将控制权交给
router.onError()。
组件内守卫
当路由进入特定组件时,可以在组件内部定义生命周期钩子:
export default {
beforeRouteEnter(to, from, next) {
// 在路由进入前调用,此时组件实例尚未创建
next();
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变但组件复用时调用
next();
},
beforeRouteLeave(to, from, next) {
// 在路由离开前调用
next();
}
};
路由独享守卫
直接在路由配置中定义,适用于单个路由的独立逻辑:
const routes = [
{
path: '/admin',
component: Admin,
beforeEnter: (to, from, next) => {
if (isAdmin()) {
next();
} else {
next('/login');
}
}
}
];
全局守卫
全局前置守卫 beforeEach 是最常用的入口,适合做登录态校验;后置钩子 afterEach 不接收 next,常用于统计或日志记录;而 beforeResolve 在所有组件内守卫和异步路由解析完成后调用,适合处理最终权限确认。
// 全局前置守卫
router.beforeEach((to, from, next) => {
if (to.path === '/protected' && !isLoggedIn()) {
next('/login');
} else {
next();
}
});
// 全局后置钩子
router.afterEach((to, from) => {
console.log('路由已切换');
// 例如:记录日志或者统计页面访问等
});
嵌套路由
构建层级页面结构时,嵌套路由非常实用。父组件模板中需包含 <router-view> 来渲染子路由:
<template>
<div>
<h2>用户页面</h2>
<router-view></router-view>
</div>
</template>
定义时注意,以 / 开头的嵌套路径被视为根路径,这允许利用组件嵌套而不必强制嵌套 URL。官方文档对此有更详细的说明:Vue Router 嵌套路由。
const routes = [
{
path: '/user',
component: User,
children: [
{ path: 'profile', component: UserProfile },
{ path: 'posts', component: UserPosts }
]
}
];
重定向与别名
重定向通过 routes 配置完成。需注意,重定向不会触发目标路由的守卫,除非目标路由本身有守卫。别名则不同,它只是映射 URL,URL 保持不变。
相对重定向示例:
const routes = [
{
path: '/users/:id/posts',
redirect: to => to.path.replace(/posts$/, 'profile')
}
];
别名常用于 UI 结构与 URL 解耦。例如,让 /people 和 /list 都指向同一个列表组件:
const routes = [
{
path: '/users',
component: UsersLayout,
children: [
{
path: '',
component: UserList,
alias: ['/people', 'list']
}
]
}
];
history 配置:指定历史模式
Vue Router 支持三种历史模式,选择取决于项目需求:
- Hash 模式 (
createWebHashHistory):默认模式,URL 带#,无需服务器配置,适合纯前端 SPA,但 SEO 效果一般。 - History 模式 (
createWebHistory):URL 更简洁,无#,但需要服务器配置回退到index.html,适合对 SEO 有要求的项目。 - Memory 模式 (
createMemoryHistory):不与 URL 交互,适合 Node 环境或 SSR。注意它没有历史记录,无法后退或前进,需在app.use(router)后手动 push 初始导航。
路由元信息(meta)
在路由配置中添加 meta 字段,可存储权限标识、页面标题等数据,配合全局守卫实现灵活控制。
const routes = [
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard,
meta: { requiresAuth: true, title: '控制面板' }
}
];
在组件中可通过 useRoute().meta 获取这些信息。
拓展
状态管理(Pinia / Vuex)
对于复杂或跨页面的数据传递,推荐使用状态管理库。Vuex 是 Vue 官方的经典方案,采用 Flux 思想,核心包括 State、Getters、Mutations 和 Actions。Pinia 则是 Vue 3 推荐的新一代方案,设计更现代化,完美支持 Composition API,且去除了 Mutations 概念,直接使用 Actions 修改状态。
Pinia 基本使用
结合插件 pinia-plugin-persistedstate 可实现数据持久化。
安装依赖:
npm install pinia pinia-plugin-persistedstate
初始化 Store:
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
doubleCount(state) {
return state.count * 2;
}
},
actions: {
increment() {
this.count++;
}
},
persist: {
enabled: true,
storage: window.localStorage
}
});
在 main.ts 中启用持久化插件:
import { createPinia } from 'pinia';
import { createPersistedState } from 'pinia-plugin-persistedstate';
const pinia = createPinia();
pinia.use(createPersistedState());
app.use(pinia);
Pinia 使用 Cookies 存储
虽然 Cookie 容量有限,但在某些场景下仍可用于简单持久化。使用时需手动处理读写逻辑:
export const useUserStore = defineStore('user', {
state: () => ({ name: null, age: null }),
actions: {
setName(name) {
this.name = name;
document.cookie = `name=${name}; path=/; max-age=3600`;
},
getName() {
const row = document.cookie.split('; ').find(r => r.startsWith('name='));
if (row) this.name = row.split('=')[1];
}
}
});
这种组合方式既利用了 Pinia 的响应式优势,又满足了特定的存储需求。


