【Vue】——路由
Vue 3 路由深入解析与实战指南
Vue Router 是 Vue.js 官方的路由管理器。它与 Vue.js 的核心深度集成,让用 Vue.js 构建单页面应用(SPA)变得轻而易举。本文将详细解析 Vue Router 4(用于 Vue 3)的核心概念和使用方法。
一、对路由的理解
什么是路由?
在传统的多页面网站中,每个页面(如 home.html
, about.html
)都是一个独立的文件。当用户点击链接时,浏览器会向服务器请求一个新的页面,这会导致整个页面刷新。
而在单页面应用(SPA)中,整个应用只有一个完整的页面(通常是 index.html
)。路由的核心作用就是:根据不同的浏览器地址(URL),动态地切换显示在这个“单页面”上的不同组件(Component),从而实现无需刷新页面的内容更新。
简单来说:路由建立了 URL 路径 与 要渲染的 Vue 组件 之间的映射关系。
工作流程:
- 用户点击页面上的路由链接。
- URL 地址栏的内容发生变化。
- 路由器(Vue Router)监测到这个变化。
- 路由器解析新的 URL,找到其配置规则中对应的组件。
- 路由器将旧的组件切换下去,将新的组件渲染到指定的路由出口(
<router-view>
)。
二、路由_基本切换效果
实现基本的路由切换需要三个核心步骤:
- 安装与引入 通过 npm 或 yarn 安装 Vue Router。
npm install vue-router@4
- 定义路由规则 (routes) 创建一个路由器实例,并定义一组路由配置,每个配置都是一个映射关系。
// router/index.jsimport { createRouter, createWebHistory } from 'vue-router'import Home from '../views/Home.vue'import About from '../views/About.vue'const routes = [{path: '/', // 访问的路径name: 'Home', // 路由名称(可选)component: Home // 要渲染的组件},{path: '/about',name: 'About',component: About}]const router = createRouter({history: createWebHistory(), // 指定历史模式routes // 路由规则配置})export default router
- 在应用中使用 在
main.js
中挂载路由器实例,并在App.vue
模板中使用<router-link>
和<router-view>
。
1、引入并使用路由器
// main.jsimport { createApp } from 'vue'import App from './App.vue'import router from './router'const app = createApp(App)app.use(router) // 挂载路由app.mount('#app')
在根组件引入并使用标签:routerview
使用routerlink给按钮绑定路径
active-class:激活后的类名
<!-- App.vue --><template><div id="app"><nav><!-- 使用 router-link 组件进行导航 --><!-- `to` 属性指定链接,它会被渲染成一个带有正确 `href` 的 `<a>` 标签 --><router-link to="/">Home</router-link> |<router-link to="/about">About</router-link></nav><!-- 路由出口 --><!-- 路由匹配到的组件将渲染在这里 --><router-view /></div></template>
效果: 点击 Home
或 About
链接,下方的 <router-view>
区域会无刷新地切换显示对应的组件内容。
三、路由_两个注意点
就看加没加routerlink
路由组件通常存放在
pages
或views
目录下,普通组件存放在components
目录下。 这样做是为了更好地区分项目的组件结构,提高代码的可维护性。通过路由切换时,被“隐藏”的路由组件实例是被销毁(unmounted)了的,需要时再去挂载(mounted)**。 这意味着组件的生命周期钩子(如
onMounted
,onUnmounted
)会随着导航的切换而触发。可以利用这一点来清除定时器、取消订阅等,防止内存泄漏。(就是一个路径切换到另一个路径)
拓展:如何区分路由组件和普通组件
定义header
使用header
现在header就是一般组件
下面的就是路由组件
Components:放一般组件
pages/views:放路由组件
关于第二个注意点可以调用两个生命周期测试
四、路由_路由器工作模式
Vue Router 有两种历史管理模式,通过 createRouter
的参数配置:
createWebHistory
(模式: ‘history’)- 创建的是正常的 URL,如
https://example.com/about
。 - 美观,没有
#
符号。这样解释代#号的
- 需要服务器支持。因为SPA只有一个
index.html
,如果用户直接访问https://example.com/about
或刷新页面,服务器必须能正确地返回index.html
文件,然后由 Vue Router 来处理路由。否则会返回 404 错误。(就像是配Nginx重定向路径一样)
- 创建的是正常的 URL,如
createWebHashHistory
(模式: ‘hash’)- 创建的 URL 中包含一个哈希字符
#
,如https://example.com/#/about
。 - 优点: 无需服务器配置。
#
之后的内容变化不会发起新的网络请求,完全由前端控制。 - 缺点: URL 看起来不美观,且 SEO 效果稍差(但现代爬虫已能很好处理)。
- 创建的 URL 中包含一个哈希字符
选择: 开发中通常使用 History
模式,部署时需要配置服务器;如果对服务器配置没有控制权,则使用 Hash
模式。
五、路由_to的两种写法
<router-link>
的 to
属性有两种写法:
- 字符串写法 (简单路径)
<router-link to="/home">Home</router-link><router-link to="/about">About</router-link>
- 对象写法 (更强大,可以传参)
<router-link :to="{ path: '/home' }">Home</router-link><router-link :to="{ name: 'user', params: { id: 123 } }">User</router-link><router-link :to="{ path: '/register', query: { plan: 'private' } }">Register</router-link>
注意:对象写法必须使用 `v-bind`(即 `:`)绑定 `to` 属性。
六、路由_命名路由
在路由配置中,可以给任何路由提供一个 name
属性。
const routes = [{path: '/user/:id',name: 'User', // 命名路由component: User}
]
这样做的好处是,在跳转时,可以绕过复杂的路径字符串,直接通过名称来引用路由。尤其是在路径很长或需要传递参数时非常方便。
三种方式都能跳转
<!-- 通过名字导航 -->
<router-link :to="{ name: 'User', params: { id: 123 } }">User</router-link>// 编程式导航
router.push({ name: 'User', params: { id: 123 } })
随着项目开发路径会越来越长,这时候后两种方法就更加适用
七、路由_嵌套路由 (子路由)
实际应用界面通常由多层嵌套的组件构成。例如,/user/profile
和 /user/posts
都是在 /user
页面下的子视图。
使用 children
配置可以实现嵌套路由:
// router/index.js
const routes = [{path: '/user/:id',component: User,children: [{// 当 /user/:id/profile 匹配成功// UserProfile 将被渲染到 User 的 <router-view> 内部path: 'profile', // 注意:不要加 `/`component: UserProfile},{path: 'posts',component: UserPosts},// 重定向到默认子路由{path: '',redirect: 'profile'}]}
]
<!-- User.vue 组件 -->
<template><div class="user"><h2>User {{ $route.params.id }}</h2><router-link :to="{ name: 'UserProfile' }">Profile</router-link><router-link :to="{ name: 'UserPosts' }">Posts</router-link><!-- 子路由的出口 --><router-view /></div>
</template>
案例:
父路由
子路由内容
添加子路径
使用routerview展示
useRouter:他是个hooks,使用他来添加参数
参数保存在query当中
前面代码完善:
父路由在routerlink后面添加参数发送数据,子路由接收数据router.query.xxx
routerlink第二种写法
第三种也可以写name
子路由接收数据可以换一种写法
解构router,注意点响应式数据结构之后会失去响应属性,要使用torefs
注意
to前面加:(这可能是省略的写法,比如value:to...)
双引号里面加反引号:是模版字符串然后就可以解析$(...)
关键点:
children
配置中的path
不能以/
开头,它是相对父路径的。- 必须在父级路由组件的模板中放置一个
<router-view>
来渲染子路由组件。
八、路由_query参数
Query 参数是附加在 URL 后面的键值对,以 ?
开头,用 &
分隔。例如:/register?plan=private&name=john
。
传递参数:
<!-- 跳转并携带query参数,to的对象写法 -->
<router-link:to="{path: '/register',query: {plan: 'private',name: 'john'}}"
>Register</router-link>
接收参数: 在目标组件中,使用 useRoute
组合式 API 或 $route
对象来获取。
<!-- 目标组件 Register.vue -->
<script setup>
import { useRoute } from 'vue-router'const route = useRoute()
// 在模板或JS中访问
console.log(route.query.plan) // 'private'
console.log(route.query.name) // 'john'
</script><template><div>Plan: {{ route.query.plan }}</div><div>Name: {{ route.query.name }}</div>
</template>
九、路由_params参数
Params 参数是定义在路由路径的一部分,属于 URL 本身。例如,路径 /user/123
中的 123
就是一个 params 参数。
修改vuerouter
使用params参数接收
重新写参数
参数的第二种写法
注意点:
一、不能用path(会自动忽略),只能使用name
错误写法
正确写法
二、不能传对象和数组
不能像下面这样传
三、加?是可选参数,传不传都可以
定义路由: 使用冒号 :
标记
{path: '/user/:id', // 动态字段以冒号开始name: 'User',component: User
}
传递参数:
<!-- 跳转并携带params参数,to的对象写法 -->
<!-- 注意:使用 params 时,不能使用 path,必须使用 name! -->
<router-link :to="{ name: 'User', params: { id: 123 } }">User 123</router-link>
接收参数: 与 Query 参数类似,通过 route.params
获取。
<script setup>
import { useRoute } from 'vue-router'const route = useRoute()
console.log(route.params.id) // '123'
</script><template><div>User ID: {{ route.params.id }}</div>
</template>
注意: Params 参数是必需的。如果路由定义为 /user/:id
,那么跳转到 /user
将会失败。可以使用可选操作符 ?
来指定一个参数是可选的:path: '/user/:id?'
。
十、路由_props配置
在组件中使用 $route
会使其与对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。props
配置可以将路由参数作为组件的 props 传递,使组件更易于复用和测试。
在路由配置中设置 props: true
:
props:true之后他会自动匹配参数
{path: '/user/:id',name: 'User',component: User,props: true // 让路由组件可以通过props接收params参数
}
然后就可以使用defineprops()接收参数了
<!-- User.vue 组件 -->
<script setup>
// 现在可以直接用 defineProps 接收,不再依赖 useRoute()
defineProps(['id'])
</script><template><div>User ID: {{ id }}</div> <!-- 直接使用 prop -->
</template>
props
配置也可以是函数模式,允许你返回一个对象作为 props,非常适合处理静态值和 query 参数。
第一种写法只适用于params
第二种可以返回各种对象,然后取自己需要的
{path: '/search',component: Search,props: (route) => ({ query: route.query.q, staticValue: 'hello' })
}
小结
使用这三种写法都是在<detail>路由组件后面继续加参数
十一、路由_replace属性
<router-link>
默认的导航行为是 push
,它会在历史记录中添加一条新记录。
设置 replace
属性后,导航不会留下历史记录,而是替换掉当前的记录,相当于调用了 router.replace()
。这意味着用户点击浏览器的后退按钮时,不能返回到上一个页面。
直接在routerlink里面添加 replace
如果想要不返回就添加replace,默认是push可以返回。
<router-link to="/home" replace>Home</router-link>
十二、路由_编程式路由导航
除了使用 <router-link>
创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。
<router-link>
最终会被转为a标签
<router-link>无法在script里面使用
在组件setup中,可以通过 useRouter
访问路由器实例。
核心方法:
router.push(location)
:导航到一个新 URL,向 history 栈添加一条新记录。(与<router-link>里面的to一样的用法
)router.replace(location)
:导航到一个新 URL,替换掉当前的 history 记录。router.go(n)
:在 history 记录中向前或向后移动多少步,类似window.history.go(n)
。
功能是在首页3秒后跳到新闻页面
案例:给按钮绑定事件
给news限制属性(只能用限制的属性,防止写错)
<script setup>
import { useRouter } from 'vue-router'const router = useRouter()const gotoHome = () => {router.push('/') // 字符串路径
}const gotoUser = () => {router.push({ name: 'User', params: { id: 123 } }) // 对象形式
}const replaceRegister = () => {router.replace({ path: '/register', query: { plan: 'private' } }) // 替换导航
}const goBack = () => {router.go(-1) // 等同于 history.back()
}
</script><template><button @click="gotoHome">Go Home</button><button @click="gotoUser">Go to User 123</button><button @click="replaceRegister">Replace to Register</button><button @click="goBack">Go Back</button>
</template>
十三、路由_重定向
重定向也是通过 routes
配置来完成。
语法: { path: 原始路径, redirect: 目标路径 }
在router文件中再添加一个首页的重定向
const routes = [{path: '/home',redirect: '/' // 访问 /home 时,重定向到 /},{path: '/old-news',redirect: '/news' // 访问 /old-news 时,重定向到 /news},{path: '/search',redirect: (to) => {// 函数方式动态返回重定向目标return { path: '/search-results', query: { q: to.query.keyword } }}},// 一种常见的用法:访问根路径时重定向到首页{path: '/',redirect: '/home'}
]
总结
Vue Router 是构建 Vue 3 单页面应用的基石。通过理解和掌握上述知识点——从基本配置、两种参数传递、嵌套路由,到更高级的编程式导航、Props 解耦和工作模式——你将能够构建出结构清晰、用户体验流畅的复杂单页应用。务必在实践中多加运用,以融会贯通。