Vue Router 是 Vue.js 官方的路由管理器,它与 Vue.js 核心深度集成,让构建单页应用(SPA)变得简单。
一、安装 Vue Router
1. 在 Vue 3 项目中安装
Vue 3 需使用 Vue Router 4+ 版本:
npm install vue-router@4 --save
# 或
yarn add vue-router@4
2. 项目结构准备
创建如下路由相关目录结构:
src/
├── router/
│ └── index.js # 路由配置文件
├── views/ # 页面级组件
│ ├── Home.vue
│ ├── About.vue
│ └── User.vue
├── App.vue
└── main.js
二、基本配置与使用
1. 创建路由实例(router/index.js)
import { createRouter, createWebHistory } from 'vue-router'
// 导入页面组件
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import User from '../views/User.vue'// 路由规则
const routes = [{path: '/', // 路径name: 'Home', // 路由名称(可选)component: Home // 对应的组件},{path: '/about',name: 'About',component: About},{path: '/user',name: 'User',component: User}
]// 创建路由实例
const router = createRouter({history: createWebHistory(), // 使用 HTML5 history 模式(无 # 号)// history: createWebHashHistory(), // 使用 hash 模式(带 # 号)routes // 注入路由规则
})export default router
2. 在 Vue 中引入路由(main.js)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 导入路由实例// 创建应用并使用路由
createApp(App).use(router) // 安装路由插件.mount('#app')
3. 路由出口与导航(App.vue)
路由出口是路由组件渲染的位置,导航用于切换路由:
<template><div id="app"><!-- 导航链接:替代 a 标签,避免页面刷新 --><nav><router-link to="/">首页</router-link> |<router-link to="/about">关于</router-link> |<router-link to="/user">用户中心</router-link></nav><!-- 路由出口:匹配的组件将在这里渲染 --><router-view /></div>
</template><style>
/* 激活的导航链接会自动添加 router-link-active 类 */
router-link-active {color: #42b983;font-weight: bold;text-decoration: none;
}
</style>
三、核心功能详解
1. 动态路由(带参数的路由)
用于匹配动态变化的路径(如 /user/123
、/user/456
):
// router/index.js 中添加动态路由
{path: '/user/:id', // :id 是动态参数name: 'UserDetail',component: () => import('../views/UserDetail.vue') // 懒加载组件
}
在组件中获取参数(UserDetail.vue):
<template><div><h2>用户详情</h2><p>用户 ID: {{ $route.params.id }}</p></div>
</template><script setup>
// 在 Composition API 中使用
import { useRoute } from 'vue-router'
const route = useRoute()
console.log('用户 ID:', route.params.id) // 输出动态参数
</script>
2. 嵌套路由
用于实现页面内的子路由(如 /about/team
、/about/history
):
// router/index.js 中配置嵌套路由
{path: '/about',name: 'About',component: About,// 子路由children: [{path: 'team', // 相对路径,完整路径是 /about/teamcomponent: () => import('../views/AboutTeam.vue')},{path: 'history', // 完整路径是 /about/historycomponent: () => import('../views/AboutHistory.vue')},{path: '', // 默认子路由(/about 时显示)component: () => import('../views/AboutIndex.vue')}]
}
在父组件(About.vue)中添加子路由出口:
<template><div><h2>关于我们</h2><!-- 子导航 --><div><router-link to="/about/team">团队</router-link> |<router-link to="/about/history">历史</router-link></div><!-- 子路由出口:子组件将在这里渲染 --><router-view /></div>
</template>
3. 编程式导航
除了 <router-link>
,还可以通过代码切换路由:
<template><button @click="goToHome">回到首页</button><button @click="goToUser(123)">查看用户 123</button>
</template><script setup>
import { useRouter } from 'vue-router'
const router = useRouter()// 跳转到首页
const goToHome = () => {router.push('/') // 通过路径跳转// 或通过路由名称跳转(更推荐,路径变化时无需修改)// router.push({ name: 'Home' })
}// 跳转到带参数的路由
const goToUser = (id) => {router.push({ name: 'UserDetail', // 使用路由名称params: { id } // 传递参数})
}// 后退/前进
const goBack = () => router.go(-1) // 后退一页
const goForward = () => router.go(1) // 前进一页
</script>
4. 路由参数与查询字符串
- params:用于动态路由参数(如
/user/:id
),必须在路由规则中定义 - query:用于查询字符串(如
/search?keyword=vue
),无需在路由规则中定义
// 跳转到带查询参数的路由
router.push({path: '/search',query: { keyword: 'vue', page: 1 } // 生成 /search?keyword=vue&page=1
})// 在组件中获取查询参数
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.query.keyword) // 输出 'vue'
5. 路由守卫
用于控制路由的访问权限(如登录验证、权限检查),分为三类:
(1)全局守卫
影响所有路由,定义在 router/index.js
中:
// 全局前置守卫:路由跳转前执行
router.beforeEach((to, from, next) => {// to: 目标路由// from: 来源路由// next(): 继续跳转;next('/login'): 跳转到登录页// 示例:未登录禁止访问个人中心const isLogin = localStorage.getItem('token')if (to.path === '/user' && !isLogin) {return next('/login') // 未登录跳转到登录页}next() // 允许跳转
})// 全局后置守卫:路由跳转后执行(无需调用 next())
router.afterEach((to, from) => {// 示例:修改页面标题document.title = to.meta.title || '我的应用'
})
(2)路由独享守卫
只影响当前路由,定义在路由规则中:
{path: '/admin',component: Admin,// 路由独享守卫beforeEnter: (to, from, next) => {// 示例:只有管理员可访问const role = localStorage.getItem('role')if (role === 'admin') {next() // 允许访问} else {next('/forbidden') // 无权限跳转到禁止页}}
}
(3)组件内守卫
在组件内部定义,控制组件的路由行为:
<script setup>
import { onBeforeRouteEnter, onBeforeRouteLeave } from 'vue-router'// 进入组件前执行(此时组件实例还未创建,不能用 this)
onBeforeRouteEnter((to, from, next) => {// 可以在这里做权限检查next()
})// 离开组件前执行
onBeforeRouteLeave((to, from, next) => {// 示例:未保存时提示if (confirm('数据未保存,确定离开吗?')) {next()} else {next(false) // 取消跳转}
})
</script>
6. 路由元信息(meta)
用于存储路由的额外信息(如标题、是否需要登录):
// 定义路由元信息
const routes = [{path: '/user',component: User,meta: { requiresAuth: true, // 需要登录title: '用户中心' // 页面标题}},{path: '/public',component: Public,meta: { requiresAuth: false, // 无需登录title: '公共页面'}}
]// 在全局守卫中使用元信息
router.beforeEach((to, from, next) => {// 检查是否需要登录if (to.meta.requiresAuth && !localStorage.getItem('token')) {next('/login')} else {next()}
})// 在后置守卫中设置标题
router.afterEach((to) => {document.title = to.meta.title || '默认标题'
})
7. 路由懒加载
减少初始加载时间,只在访问路由时才加载组件:
// 普通加载(会一次性加载所有组件)
import Home from '../views/Home.vue'// 懒加载(推荐)
const About = () => import('../views/About.vue')// 路由配置中直接使用
const routes = [{path: '/about',component: () => import('../views/About.vue') // 直接在路由中定义}
]
四、常见问题与最佳实践
-
history 模式与 hash 模式的区别:
createWebHistory()
:URL 无#
号,需服务器配置支持(避免刷新 404)createWebHashHistory()
:URL 带#
号,无需服务器配置,兼容性更好
-
避免路由冗余:
- 使用路由名称(
name
)跳转,而非硬编码路径 - 提取公共路由配置(如需要登录的路由可统一处理)
- 使用路由名称(
-
路由模块化:大型项目可拆分路由配置:
// router/modules/user.js export default [{ path: '/user', component: User },{ path: '/user/:id', component: UserDetail } ]// router/index.js 中合并 import userRoutes from './modules/user' const routes = [...userRoutes, ...otherRoutes]
五、总结
- 路由的基本配置与使用
- 动态路由、嵌套路由、编程式导航
- 路由守卫与权限控制
- 路由元信息与懒加载