【Vue3】【笔记】----第六章:Vue3 路由(Vue Router 4 从入门到实战)
·
文章目录
第六章:Vue3 路由(Vue Router 4 从入门到实战)
一、入门:路由核心概念与环境搭建
- 为什么需要路由?在单页应用(SPA)中,页面内容切换无需刷新浏览器,而是通过“路由”实现URL与组件的映射——用户访问不同URL,路由匹配对应的组件并渲染,这是Vue项目实现多页面交互的核心。
- Vue Router 4 核心概念:
- 路由规则(Routes):数组形式,每个规则包含
path(URL路径)、component(对应组件)、name(路由名称,可选)等属性,定义“URL→组件”的映射关系。 - 路由实例(Router Instance):用
createRouter创建,传入路由规则和模式(history或hash),挂载到Vue应用后生效。 - 路由视图(Router View):用
<router-view>组件占位,路由匹配的组件会渲染到这个位置,是页面内容的“容器”。 - 路由链接(Router Link):用
<router-link>组件替代<a>标签实现页面跳转,避免刷新浏览器,通过to属性指定目标URL。
- 路由规则(Routes):数组形式,每个规则包含
- 环境搭建步骤(详细版):
- 第一步:安装依赖。在Vue3项目中执行命令:
npm install vue-router@4(需指定版本4,避免安装旧版Vue Router 3)。 - 第二步:创建路由配置文件。在
src目录下新建router文件夹,创建index.js作为路由核心配置文件,初始代码如下:
// src/router/index.js // 1. 引入路由核心函数和组件 import { createRouter, createWebHistory } from 'vue-router' // 引入需要匹配的组件(可提前创建Home和About组件) import Home from '@/views/Home.vue' import About from '@/views/About.vue' // 2. 定义路由规则数组 const routes = [ { path: '/', // URL路径(根路径) name: 'Home', // 路由名称(可选,用于命名路由跳转) component: Home // 对应渲染的组件 }, { path: '/about', name: 'About', component: About } ] // 3. 创建路由实例 const router = createRouter({ // 路由模式:createWebHistory() 对应 HTML5 History 模式(URL无#),createWebHashHistory() 对应 Hash 模式(URL含#) history: createWebHistory(import.meta.env.BASE_URL), // import.meta.env.BASE_URL 是项目基础路径,在vite.config.js中配置 routes // 传入路由规则 }) // 4. 导出路由实例,供main.js挂载 export default router- 第三步:全局挂载路由。在
src/main.js中引入路由实例,通过app.use(router)挂载:
// src/main.js import { createApp } from 'vue' import App from './App.vue' import router from './router' // 引入路由实例 const app = createApp(App) app.use(router) // 挂载路由 app.mount('#app')- 第四步:添加路由视图和路由链接。在
src/App.vue中,用<router-link>实现跳转,用<router-view>渲染组件:
<!-- src/App.vue --> <template> <div class="app"> <!-- 路由链接:to属性指定目标路径,active-class指定激活时的样式(可选) --> <nav> <router-link to="/" active-class="active">首页</router-link> <router-link to="/about" active-class="active">关于我们</router-link> </nav> <!-- 路由视图:匹配的组件会渲染到这里 --> <router-view class="content" /> </div> </template> <style> .active { color: #42b983; font-weight: bold; } /* 激活路由的样式 */ .content { margin-top: 20px; } </style>- 第五步:验证效果。执行
npm run dev启动项目,点击“首页”“关于我们”,URL会切换(无#,History模式),页面内容实时切换且不刷新,说明路由配置成功。
- 第一步:安装依赖。在Vue3项目中执行命令:
二、精通:路由进阶功能与场景适配
1. 动态路由与路由传参(核心高频场景)
动态路由用于匹配“路径规则相同但参数不同”的URL,比如“商品详情页”——所有商品的详情页路径都是/goods/商品ID,通过动态参数id区分不同商品。
- 第一步:定义动态路由规则。在
routes数组中,用:参数名表示动态参数:
// src/router/index.js
import GoodsDetail from '@/views/GoodsDetail.vue' // 引入商品详情组件
const routes = [
// ...其他路由
{
path: '/goods/:id', // :id 是动态参数,匹配 /goods/1、/goods/100 等路径
name: 'GoodsDetail', // 命名路由,方便传参
component: GoodsDetail,
// 可选:明确指定路由参数的类型(避免类型错误,支持TypeScript)
props: route => ({ id: Number(route.params.id) }) // 将params.id转为Number类型,通过props传给组件
}
]
- 第二步:路由传参的3种方式(场景对比):
- 方式1:动态路由参数(
params传参)。适合传递“必需参数”(如商品ID),参数会显示在URL中:- 跳转方式1(
<router-link>):<router-link :to="'/goods/' + goodsId">查看详情</router-link>(goodsId是组件中的变量,如1)。 - 跳转方式2(编程式导航,适合点击按钮后执行逻辑再跳转):
import { useRouter } from 'vue-router' // 引入路由钩子 const router = useRouter() // 创建路由实例 const goToDetail = (goodsId) => { // 方式2.1:通过path跳转,params需在path中拼接 router.push(`/goods/${goodsId}`) // 方式2.2:通过name跳转,params作为单独参数(推荐,更清晰) // router.push({ name: 'GoodsDetail', params: { id: goodsId } }) }- 组件中接收参数:通过
useRoute钩子获取路由信息,或通过props接收(需在路由规则中配置props):
// 方式1:用useRoute获取 import { useRoute } from 'vue-router' const route = useRoute() const goodsId = route.params.id // 注意:params参数默认是字符串类型,需手动转数字 // 方式2:通过props接收(推荐,更符合组件化思想) // GoodsDetail.vue 中 const props = defineProps({ id: { type: Number, required: true // 必传参数 } }) console.log(props.id) // 直接使用,已转为Number类型 - 跳转方式1(
- 方式2:查询参数(
query传参)。适合传递“可选参数”(如分页、筛选条件),参数以?key=value形式显示在URL中(如/goods/1?tab=comment):- 编程式导航跳转:
router.push({ name: 'GoodsDetail', // 也可用path: '/goods/1' query: { tab: 'comment', page: 1 } // query参数,可传多个 })- 组件中接收:
const tab = route.query.tab(默认字符串类型,如'comment')。
- 方式3:路由元信息(
meta传参)。适合传递“路由配置相关的静态信息”(如页面标题、是否需要登录),参数不显示在URL中,仅在路由规则中定义:- 定义路由规则时添加
meta:
const routes = [ { path: '/about', name: 'About', component: About, meta: { title: '关于我们', // 页面标题 requiresAuth: false // 是否需要登录(后续权限控制用) } }, { path: '/user', name: 'User', component: () => import('@/views/User.vue'), // 懒加载(后续讲) meta: { title: '个人中心', requiresAuth: true // 需要登录才能访问 } } ]- 组件中获取:
const pageTitle = route.meta.title。
- 定义路由规则时添加
- 方式1:动态路由参数(
2. 路由懒加载(优化性能核心手段)
默认情况下,Vue项目打包时会将所有路由组件合并到一个JS文件中,导致文件体积过大,首屏加载速度慢。路由懒加载通过“按需加载”——只有当用户访问该路由时,才加载对应的组件JS文件,减小首屏加载体积。
- 实现方式:将路由规则中
component的“静态引入”改为“动态import函数引入”,代码如下:
// src/router/index.js
// 静态引入(不推荐,会打包到主文件)
// import User from '@/views/User.vue'
// 动态引入(路由懒加载,推荐)
const User = () => import('@/views/User.vue')
const routes = [
{
path: '/user',
name: 'User',
component: User // 使用懒加载组件
// 可选:给懒加载的组件分组(打包时合并到同一个JS文件)
// component: () => import(/* webpackChunkName: "user" */ '@/views/User.vue')
},
// 更简洁的写法:直接在component中写动态import
{
path: '/order',
name: 'Order',
component: () => import('@/views/Order.vue')
}
]
- 效果验证:启动项目后,首次加载仅加载首页相关JS文件;访问
/user时,浏览器会额外加载User.vue对应的JS文件(可在Chrome开发者工具“Network”面板查看)。
3. 嵌套路由(实现页面布局复用)
当多个页面有相同的“公共布局”(如左侧菜单、顶部导航),可通过嵌套路由实现——公共布局作为“父路由组件”,不同内容作为“子路由组件”,渲染到父组件的<router-view>中。
- 示例:实现“用户中心”页面,包含“个人信息”“我的订单”两个子页面,共享顶部导航。
- 第一步:创建父路由组件(
UserLayout.vue),在组件中添加<router-view>用于渲染子组件:
<!-- src/views/UserLayout.vue(父路由组件) -->
<template>
<div class="user-layout">
<!-- 公共顶部导航 -->
<div class="user-header">个人中心</div>
<!-- 子路由组件渲染位置 -->
<router-view class="user-content" />
</div>
</template>
<style>
.user-header { padding: 16px; border-bottom: 1px solid #eee; }
.user-content { padding: 16px; }
</style>
- 第二步:创建子路由组件(
UserProfile.vue、UserOrders.vue),分别实现“个人信息”和“我的订单”内容。 - 第三步:配置嵌套路由规则,在父路由的
children数组中定义子路由:
// src/router/index.js
const routes = [
{
path: '/user',
name: 'User',
component: () => import('@/views/UserLayout.vue'), // 父路由组件
meta: { requiresAuth: true },
// 子路由规则(children数组)
children: [
{
// 子路由path不加/,表示相对父路由路径(即 /user/profile)
path: 'profile',
name: 'UserProfile',
component: () => import('@/views/UserProfile.vue'),
meta: { title: '个人信息' }
},
{
path: 'orders',
name: 'UserOrders',
component: () => import('@/views/UserOrders.vue'),
meta: { title: '我的订单' }
},
// 子路由默认跳转:当访问 /user 时,自动跳转到 /user/profile
{
path: '',
redirect: 'profile'
}
]
}
]
- 第四步:添加子路由链接。在父路由组件(
UserLayout.vue)中添加<router-link>,实现子页面切换:
<!-- UserLayout.vue 中 -->
<template>
<div class="user-layout">
<div class="user-header">个人中心</div>
<!-- 子路由链接 -->
<div class="user-tabs">
<router-link to="/user/profile" active-class="active">个人信息</router-link>
<router-link to="/user/orders" active-class="active">我的订单</router-link>
</div>
<router-view class="user-content" />
</div>
</template>
<style>
.user-tabs { margin: 16px 0; display: flex; gap: 20px; }
.user-tabs .active { color: #42b983; border-bottom: 2px solid #42b983; }
</style>
- 效果:访问
/user时,自动渲染UserLayout和UserProfile;点击“我的订单”,URL变为/user/orders,UserLayout保持不变,仅中间内容切换为UserOrders。
4. 路由守卫(实现权限控制与页面拦截)
路由守卫是“路由跳转前后执行的钩子函数”,可用于权限控制(如未登录拦截到登录页)、页面标题修改、埋点统计等场景。Vue Router 4 提供3类守卫:全局守卫、路由独享守卫、组件内守卫。
- 场景1:全局前置守卫(
beforeEach)——未登录拦截。所有路由跳转前都会执行,适合全局权限控制:
// src/router/index.js
import { useUserStore } from '@/store/userStore' // 引入用户Store(第五章创建的)
// 全局前置守卫:跳转前执行
router.beforeEach((to, from, next) => {
// to:即将跳转到的路由对象
// from:当前要离开的路由对象
// next:函数,控制是否允许跳转(Vue Router 4 中可直接返回true/false或路由对象,next已废弃但仍兼容)
// 1. 修改页面标题(利用路由meta信息)
document.title = to.meta.title || 'Vue3 路由示例'
// 2. 权限控制:判断目标路由是否需要登录(requiresAuth为true)
const userStore = useUserStore() // 创建用户Store实例
const requiresAuth = to.meta.requiresAuth
if (requiresAuth && !userStore.isLogin) {
// 未登录且需要登录,拦截到登录页,并记录当前路由(登录后可跳回)
return {
name: 'Login', // 登录页路由名称(需提前创建Login组件和路由)
query: { redirect: to.fullPath } // 记录当前要访问的路径,存到query参数
}
}
// 允许跳转
return true
})
- 场景2:组件内守卫——离开页面时提示未保存的内容。在组件中定义,仅当前组件对应的路由生效:
<!-- UserProfile.vue(个人信息组件) -->
<script setup>
import { onBeforeRouteLeave } from 'vue-router'
import { ref } from 'vue'
const isEdited = ref(false) // 标记是否修改了内容未保存
// 组件内守卫:离开当前路由前执行
onBeforeRouteLeave((to, from, next) => {
if (isEdited.value) {
const confirmLeave = window.confirm('内容未保存,确定要离开吗?')
if (confirmLeave) {
next() // 确认离开,允许跳转
} else {
next(false) // 取消离开,阻止跳转
}
} else {
next() // 无未保存内容,允许跳转
}
})
</script>
三、实战:路由综合案例(用户登录与个人中心)
- 需求拆解:实现“登录页→首页→个人中心(含子页面)”的完整流程,包含:未登录访问个人中心拦截到登录页、登录后跳回原目标页面、个人中心子页面切换、页面标题动态修改。
- 前置准备:已创建以下组件和配置:
- 组件:
Login.vue(登录页)、Home.vue(首页)、UserLayout.vue(个人中心父组件)、UserProfile.vue(个人信息)、UserOrders.vue(我的订单)。 - 路由:已配置上述组件的路由,且
/user及子路由的meta.requiresAuth设为true
- 组件:
更多推荐
所有评论(0)