Vue3 路由:构建灵活高效的单页应用
目录
在现代前端开发中,单页应用(SPA)已成为主流架构模式,而路由系统作为 SPA 的核心基础设施,承担着页面跳转、状态管理、权限控制等关键职责。Vue3 作为当前最流行的前端框架之一,其配套的路由解决方案 Vue Router 4(以下简称 Vue Router)针对 Composition API 进行了全面优化,提供了更简洁的语法、更强大的功能和更优的性能。本文将从基础配置到高级实战,全方位解析 Vue3 路由的使用技巧与最佳实践,帮助开发者轻松构建灵活、高效、可扩展的路由系统
一、Vue3 路由基础配置:从入门到上手
1. 路由实例创建与挂载
Vue Router 4 的基础配置流程简洁清晰,核心步骤包括创建路由实例、定义路由规则、挂载到 Vue 应用。
首先,在项目 src 目录下创建 router 文件夹,新建 index.ts 文件,编写路由配置:
// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
// 导入组件(可采用懒加载方式)
import Home from '@/views/Home.vue';
import About from '@/views/About.vue';
// 定义路由规则,RouteRecordRaw为类型定义,确保配置规范
const routes: Array<RouteRecordRaw> = [
{
path: '/', // 路由路径
name: 'Home', // 路由名称(可选,用于编程式导航)
component: Home, // 对应组件
meta: {
title: '首页', // 元信息,可存储页面标题、权限等自定义数据
requiresAuth: false // 是否需要登录权限
}
},
{
path: '/about',
name: 'About',
component: About,
meta: {
title: '关于我们',
requiresAuth: false
}
},
// 404页面配置
{
path: '/:pathMatch(.*)*', // 匹配所有未定义的路由
name: 'NotFound',
component: () => import('@/views/NotFound.vue'), // 懒加载组件
meta: {
title: '页面未找到'
}
}
];
// 创建路由实例
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), // History模式
routes // 传入路由规则
});
export default router;
然后,在 main.ts 中挂载路由实例:
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router'; // 导入路由实例
const app = createApp(App);
app.use(router); // 挂载路由
app.mount('#app');
最后,在 App.vue 中使用<router-view>组件渲染路由对应的组件,<router-link>组件实现导航跳转:
<!-- src/App.vue -->
<template>
<div class="app">
<!-- 导航栏,router-link会被渲染为a标签,active-class指定激活样式 -->
<nav>
<router-link to="/" active-class="active">首页</router-link>
<router-link to="/about" active-class="active">关于我们</router-link>
</nav>
<!-- 路由组件渲染出口 -->
<router-view />
</div>
</template>
<style scoped>
.active {
color: #42b983;
font-weight: bold;
text-decoration: none;
margin: 0 10px;
}
</style>
2. 路由跳转的两种方式
Vue Router 支持声明式导航和编程式导航两种跳转方式,满足不同场景需求。
(1)声明式导航
通过<router-link>组件实现,无需编写 JavaScript 代码,适用于静态导航场景。核心属性包括:
(1)to:指定跳转路径,支持字符串(如to="/about")或对象(如to="{ name: 'About' }");
(2)replace:跳转时替换历史记录,点击后退不会返回上一级页面;
(3)active-class:路由激活时的样式类名;
(4)exact:精确匹配路由(Vue Router 4 中默认开启精确匹配,无需手动设置)。
<!-- 字符串形式 -->
<router-link to="/about">关于我们</router-link>
<!-- 对象形式,通过name匹配路由(需路由配置中定义name) -->
<router-link :to="{ name: 'About' }">关于我们</router-link>
<!-- 带查询参数 -->
<router-link :to="{ path: '/user', query: { id: 1 } }">用户中心</router-link>
<!-- 替换历史记录 -->
<router-link to="/about" replace>关于我们</router-link>
(2)编程式导航
通过路由实例的方法实现跳转,适用于需要逻辑判断的动态导航场景。核心方法包括:
(1)push:添加新的历史记录,跳转后可通过后退返回;
(2)replace:替换当前历史记录,跳转后无法返回;
(3)go:前进或后退指定步数(如go(-1)表示后退一页)。
在 Vue3 的 setup 函数中,需通过useRouter获取路由实例:
<!-- src/views/Home.vue -->
<template>
<button @click="goToAbout">跳转到关于我们</button>
<button @click="goToUser">跳转到用户中心</button>
<button @click="goBack">后退</button>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router';
const router = useRouter();
// 跳转到About页面
const goToAbout = () => {
// 字符串形式
router.push('/about');
// 或对象形式
// router.push({ name: 'About' });
};
// 跳转到User页面并携带查询参数
const goToUser = () => {
router.push({
path: '/user',
query: { id: 1, name: '张三' }
});
};
// 后退一页
const goBack = () => {
router.go(-1);
};
</script>
3. 路由参数的传递与接收
路由参数是组件间传递数据的重要方式,Vue Router 支持两种参数类型:查询参数(query)和动态路由参数(params)。
(1)查询参数(query)
(1)特点:参数会拼接在 URL 后面,格式为?key=value,支持多个参数(用&分隔);
(2)优点:刷新页面后参数不会丢失,可用于分享链接;
(3)接收方式:通过useRoute钩子获取route.query。
<!-- 传递参数 -->
<router-link :to="{ path: '/user', query: { id: 1, name: '张三' } }">用户中心</router-link>
<!-- 接收参数 -->
<script setup lang="ts">
import { useRoute } from 'vue-router';
const route = useRoute();
// 类型断言,确保参数类型正确
const userId = route.query.id as string;
const userName = route.query.name as string;
console.log('用户ID:', userId, '用户名:', userName);
</script>
(2)动态路由参数(params)
(1)特点:参数嵌入 URL 路径中,格式为/path/:paramName,需在路由配置中声明;
(2)优点:URL 更简洁,语义化更强;
(3)注意:刷新页面后参数会丢失(需配合本地存储或后端接口);
(4)接收方式:通过useRoute钩子获取route.params。
示例:首先,在路由配置中声明动态参数:
// src/router/index.ts
const routes: Array<RouteRecordRaw> = [
{
path: '/user/:id', // 动态参数id
name: 'User',
component: () => import('@/views/User.vue'),
meta: { title: '用户中心' }
}
];
然后,传递和接收参数:
<!-- 传递参数 -->
<router-link :to="{ name: 'User', params: { id: 1 } }">用户中心</router-link>
<!-- 接收参数 -->
<script setup lang="ts">
import { useRoute } from 'vue-router';
const route = useRoute();
// 动态路由参数的类型为string
const userId = route.params.id as string;
console.log('用户ID:', userId);
</script>
二、嵌套路由:构建复杂页面结构
在实际项目中,页面通常包含多级导航(如顶部导航 + 侧边栏导航),此时需要使用嵌套路由来实现页面结构的层级化。嵌套路由的核心是在父路由中通过children属性定义子路由,同时在父组件中使用<router-view>渲染子组件。
1. 嵌套路由配置
以 “后台管理系统” 为例,父路由为/admin,子路由包括/admin/dashboard(仪表盘)、/admin/user-manage(用户管理):
// src/router/index.ts
const routes: Array<RouteRecordRaw> = [
{
path: '/admin',
name: 'Admin',
component: () => import('@/views/Admin.vue'), // 父组件
meta: { requiresAuth: true }, // 需要登录权限
children: [ // 子路由配置
{
path: 'dashboard', // 子路由路径(无需加/,会自动拼接父路由路径)
name: 'Dashboard',
component: () => import('@/views/admin/Dashboard.vue'),
meta: { title: '仪表盘' }
},
{
path: 'user-manage',
name: 'UserManage',
component: () => import('@/views/admin/UserManage.vue'),
meta: { title: '用户管理' }
},
{
path: '', // 子路由默认路径,访问/admin时自动跳转到此
redirect: 'dashboard'
}
]
}
];
2. 父组件中渲染子路由
在父组件Admin.vue中,需要包含子路由的导航和渲染出口:
<!-- src/views/Admin.vue -->
<template>
<div class="admin-container">
<!-- 侧边栏导航(子路由导航) -->
<aside class="sidebar">
<router-link to="/admin/dashboard" active-class="active">仪表盘</router-link>
<router-link to="/admin/user-manage" active-class="active">用户管理</router-link>
</aside>
<!-- 子路由渲染出口 -->
<main class="content">
<router-view />
</main>
</div>
</template>
<style scoped>
.admin-container {
display: flex;
height: 100vh;
}
.sidebar {
width: 200px;
background: #f5f5f5;
padding: 20px;
}
.sidebar a {
display: block;
margin: 10px 0;
text-decoration: none;
color: #333;
}
.active {
color: #42b983 !important;
font-weight: bold;
}
.content {
flex: 1;
padding: 20px;
}
</style>
此时,访问/admin会自动跳转到/admin/dashboard,侧边栏导航点击后,子路由组件会在<main class="content">中渲染,实现了页面结构的层级化管理。
三、路由懒加载:优化项目性能
在大型项目中,若一次性加载所有路由组件,会导致初始打包体积过大,页面加载速度变慢。路由懒加载(也称代码分割)可将不同路由对应的组件分割为独立的代码块,只有当用户访问该路由时才会加载对应的代码,从而优化首屏加载性能。
Vue Router 4 支持两种路由懒加载方式:动态导入(推荐)和defineAsyncComponent(Vue3 新增)。
1. 动态导入方式
这是最常用的懒加载方式,通过 ES6 的import()语法实现,无需额外配置。
// src/router/index.ts
const routes: Array<RouteRecordRaw> = [
{
path: '/about',
name: 'About',
// 动态导入组件,打包时会分割为独立的代码块
component: () => import('@/views/About.vue'),
meta: { title: '关于我们' }
},
{
path: '/admin',
name: 'Admin',
component: () => import('@/views/Admin.vue'),
children: [
{
path: 'dashboard',
component: () => import('@/views/admin/Dashboard.vue') // 子路由也支持懒加载
}
]
}
];
2. 定义命名代码块
若需将多个路由组件打包到同一个代码块中,可在import()中指定webpackChunkName(webpack 支持):
// 多个组件打包到admin chunk中
component: () => import(/* webpackChunkName: "admin" */ '@/views/admin/Dashboard.vue')
3. defineAsyncComponent 方式
Vue3 的defineAsyncComponent函数可用于定义异步组件,支持更灵活的加载配置(如加载状态、错误处理),也可用于路由懒加载。
// src/router/index.ts
import { defineAsyncComponent } from 'vue';
const routes: Array<RouteRecordRaw> = [
{
path: '/user',
name: 'User',
component: defineAsyncComponent({
loader: () => import('@/views/User.vue'), // 加载组件
loadingComponent: () => import('@/components/Loading.vue'), // 加载中状态组件
errorComponent: () => import('@/components/Error.vue'), // 加载失败组件
delay: 200, // 延迟显示加载组件(避免闪烁)
timeout: 5000 // 超时时间,超过则显示错误组件
})
}
];
四、Vue3 路由总结
(1)规范路由配置:使用RouteRecordRaw类型定义路由规则,确保配置规范;为路由添加name属性,便于编程式导航;合理使用meta存储页面标题、权限等元信息。
(2)优先使用 Composition API:在 setup 函数中使用useRoute、useRouter替代this.$route、this.$router,配合 TypeScript 获得更好的类型支持。
(3)全面使用路由懒加载:对所有非首屏路由组件采用懒加载,减少初始打包体积;合理划分代码块,避免过多小体积代码块。
(4)精细化权限控制:结合路由元信息和全局守卫,实现基于角色或权限的访问控制;对无权限路由及时重定向,提升用户体验。
(5)优化路由跳转体验:使用scrollBehavior控制滚动行为;在组件内守卫中处理未保存数据的提示;为异步路由添加加载状态组件。
(6)避免路由冗余:合理使用嵌套路由简化页面结构;通过redirect处理默认路由和旧路由兼容。
(7)加强错误处理:配置 404 页面处理无效路由;在路由守卫和异步组件中处理错误场景,避免页面崩溃。
更多推荐


所有评论(0)