Vue3 路由(Vue Router)
本章节我们将为大家介绍 Vue 路由。
Vue 路由允许我们通过不同的 URL 访问不同的内容。
通过 Vue 可以实现多视图的单页 Web 应用(single page web application,SPA)。
Vue.js 路由需要载入 vue-router 库
中文文档地址:vue-router 文档。
Vue Router 负责将 URL 路径与应用中的组件进行映射,当用户在应用中浏览时,URL 会更新,但页面不会重新加载,从而提供流畅的用户体验。

上图展示了一个两层级的嵌套路由结构:
- 顶层 (
App.vue的<router-view>) 负责渲染独立布局(如Login.vue)或主框架布局(Layout.vue)。 - 主框架布局 (
Layout.vue) 内部包含第二个<router-view>,用于渲染功能页面的子组件(如Dashboard.vue、User.vue),从而实现页头、侧边栏和页脚的持久化显示。 - 未匹配的路径最终会导向独立的
page404.vue。
核心组成部分
| 组成部分 | 描述 | 选项式 API 访问 | 组合式 API 访问 |
|---|---|---|---|
router 实例 |
整个路由系统的实例,用于全局导航、添加路由等。 | this.$router |
useRouter() |
route 对象 |
当前激活的路由状态对象,包含当前 URL、参数、查询等信息。 | this.$route |
useRoute() |
<router-link> |
用于在应用中进行导航的组件,会被渲染成一个 <a> 标签,但可以阻止默认的页面刷新。 |
- | - |
<router-view> |
路由匹配到的组件将渲染在这个位置。 | - | - |
安装
npm 安装
npm install vue-router
npm(国内镜像)
推荐使用淘宝镜像:
npm install -g cnpm --registry=https://registry.npmmirror.com cnpm install vue-router@4
直接下载 / CDN
https://unpkg.com/vue-router@4
基本应用
1、创建路由表
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
export default createRouter({
history: createWebHistory(),
routes
})
2、在应用中挂载
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
3、页面出口
<router-view></router-view>
4、跳转
<router-link to="/about">About</router-link>
5、动态路由
{ path: '/user/:id', component: User }
访问 /user/10,$route.params.id === '10'。
6、懒加载
const About = () => import('../views/About.vue')
7、导航守卫(鉴权)
router.beforeEach((to, from, next) => {
next()
})
8、重定向
{ path: '/old', redirect: '/' }
9、404
{ path: '/:pathMatch(.*)*', component: NotFound }
简单实例
Vue.js + vue-router 可以很简单的实现单页应用。
<router-link> 是一个组件,该组件用于设置一个导航链接,切换不同 HTML 内容。 to 属性为目标地址, 即要显示的内容。
以下实例中我们将 vue-router 加进来,然后配置组件和路由映射,再告诉 vue-router 在哪里渲染它们。代码如下所示:
HTML 代码
router-link
请注意,我们没有使用常规的 a 标签,而是使用一个自定义组件 router-link 来创建链接。这使得 Vue Router 可以在不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码。我们将在后面看到如何从这些功能中获益。
router-view
router-view 将显示与 url 对应的组件。你可以把它放在任何地方,以适应你的布局。
JavaScript 代码
尝试一下 »
点击过的导航链接都会加上样式 class ="router-link-exact-active router-link-active"。
应用实例
以下例子涵盖了路由的定义、创建、挂载、导航和渲染五个核心步骤。
1. main.js (入口文件)
实例
import App from './App.vue';
import router from './router'; // 导入配置好的路由实例
// 1. 创建 Vue 应用实例
const app = createApp(App);
// 2. 挂载路由
app.use(router);
// 3. 挂载到 DOM
app.mount('#app');
2. router/index.js (路由配置)
实例
// 导入路由组件 (这里使用同步导入简化示例)
const Home = { template: '<h2>Home Page</h2><p>Welcome to the application home!</p>' };
const About = { template: '<h2>About Us</h2><p>Learn more about this project.</p>' };
// 定义路由记录数组
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
// 404 匹配 (放在最后)
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: { template: '<div>404 Not Found</div>' }
}
];
// 创建 Router 实例
const router = createRouter({
// 使用 HTML5 History 模式 (推荐)
history: createWebHistory(),
routes, // 路由配置
});
export default router;
3. App.vue (根组件)
实例
<div>
<h1>Vue Router 示例</h1>
<nav>
<router-link to="/" active-class="active-link">Home</router-link> |
<router-link to="/about" active-class="active-link">About</router-link> |
<router-link to="/nonexistent">404 Demo</router-link>
</nav>
<hr>
<main>
<router-view></router-view>
</main>
</div>
</template>
<style>
/* 简单的激活样式 */
.active-link {
font-weight: bold;
color: #42b983; /* Vue 绿色 */
}
/* 调整链接间距 */
nav a {
margin: 0 5px;
text-decoration: none;
}
</style>
当您运行此应用时:
- 点击 Home 链接,URL 变为
/,<router-view>中显示Home Page组件内容。 - 点击 About 链接,URL 变为
/about,<router-view>中显示About Us组件内容。 - 点击 404 Demo 链接,URL 变为
/nonexistent,<router-view>中显示404 Not Found组件内容。
<router-link> 相关属性
接下来我们可以了解下更多关于 <router-link> 的属性。
to
表示目标路由的链接。 当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。
<!-- 字符串 -->
<router-link to="home">Home</router-link>
<!-- 渲染结果 -->
<a href="home">Home</a>
<!-- 使用 v-bind 的 JS 表达式 -->
<router-link v-bind:to="'home'">Home</router-link>
<!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
<router-link :to="'home'">Home</router-link>
<!-- 同上 -->
<router-link :to="{ path: 'home' }">Home</router-link>
<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
<!-- 带查询参数,下面的结果为 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
replace
设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。
<router-link :to="{ path: '/abc'}" replace></router-link>
append
设置 append 属性后,则在当前 (相对) 路径前添加其路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
<router-link :to="{ path: 'relative/path'}" append></router-link>
tag
有时候想要 <router-link> 渲染成某种标签,例如 <li>。
于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。
<router-link to="/foo" tag="li">foo</router-link> <!-- 渲染结果 --> <li>foo</li>
active-class
设置 链接激活时使用的 CSS 类名。可以通过以下代码来替代。
<style>
._active{
background-color : red;
}
</style>
<p>
<router-link v-bind:to = "{ path: '/route1'}" active-class = "_active">Router Link 1</router-link>
<router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
</p>
注意这里 class 使用 active-class="_active"。
exact-active-class
配置当链接被精确匹配的时候应该激活的 class。可以通过以下代码来替代。
<p>
<router-link v-bind:to = "{ path: '/route1'}" exact-active-class = "_active">Router Link 1</router-link>
<router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
</p>
event
声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。
<router-link v-bind:to = "{ path: '/route1'}" event = "mouseover">Router Link 1</router-link>
以上代码设置了 event 为 mouseover ,及在鼠标移动到 Router Link 1 上时导航的 HTML 内容会发生改变。
Vue Router (v4, Vue 3) 核心 API 手册
一、createRouter 配置项
| 配置项 | 用途 | 示例 |
|---|---|---|
history |
指定 URL 模式 | createWebHistory() |
routes |
路由表定义数组 | [{ path: '/', component: Home }] |
scrollBehavior |
控制页面滚动位置 | { top: 0 } |
strict |
是否严格区分结尾斜杠 | true |
linkActiveClass |
链接激活时的 Class | 'active' |
linkExactActiveClass |
链接精确激活时的 Class | 'exact-active' |
parseQuery |
自定义 URL Query 解析 | (q) => ({...}) |
stringifyQuery |
自定义 URL Query 序列化 | (obj) => 'a=1' |
二、History 工厂
| API | 用途 | 示例 |
|---|---|---|
createWebHistory() |
使用 HTML5 History 模式(推荐) | createWebHistory() |
createWebHashHistory() |
使用 Hash 模式(URL 带 #) |
createWebHashHistory() |
createMemoryHistory() |
适用于 SSR (服务端渲染) | createMemoryHistory() |
三、RouteRecord (路由表项)
| 字段 | 用途 | 示例 |
|---|---|---|
path |
路由路径定义 | /user/:id |
name |
路由命名 | name: 'User' |
component |
对应的主组件 | UserView |
components |
用于命名视图 (多 <router-view>) |
{ default: A, left: B } |
redirect |
重定向目标 | redirect: '/login' |
children |
定义嵌套子路由 | [ { path: 'profile' } ] |
props |
将 params 自动转为组件 props |
props: true |
meta |
自定义元信息字段 | { auth: true } |
alias |
为当前路由添加别名(多入口) | alias: '/b' |
beforeEnter |
路由独享导航守卫 | { beforeEnter: (to,from,next)=>{} } |
四、路由导航 (Router 实例方法)
| Router API | 用途 | 示例 |
|---|---|---|
router.push(to) |
编程式跳转,向 history 栈添加新记录 | router.push('/a') |
router.replace(to) |
编程式跳转,替换当前 history 记录 | router.replace('/a') |
router.back() |
后退一步 | router.back() |
router.forward() |
前进一步 | router.forward() |
router.go(n) |
手动偏移 history 栈 | router.go(-1) |
router.addRoute(route) |
动态添加路由记录 | router.addRoute({ name:'Post', ... }) |
router.removeRoute(name) |
通过名称移除路由记录 | router.removeRoute('user') |
router.getRoutes() |
获取所有路由记录 | router.getRoutes() |
router.hasRoute(name) |
判断是否存在指定名称的路由 | router.hasRoute('user') |
五、导航守卫
| 守卫 | 作用域 | 钩子签名 |
|---|---|---|
router.beforeEach |
全局前置 | (to, from, next) => {} |
router.beforeResolve |
全局解析阶段(在组件内守卫和异步组件解析后) | (to, from, next) => {} |
router.afterEach |
全局后置(不能阻止导航) | (to, from, failure) => {} |
beforeEnter |
路由独享 | beforeEnter: (to, from, next) => {} |
beforeRouteEnter |
组件内 (访问不到 this) |
beforeRouteEnter(to, from, next) {} |
beforeRouteUpdate |
组件内 (当前路由复用时,如参数变化) | beforeRouteUpdate(to, from, next) {} |
beforeRouteLeave |
组件内 (离开该组件时) | beforeRouteLeave(to, from, next) {} |
六、<router-link> 属性
| 属性 | 用途 | 示例 |
|---|---|---|
to |
目标路由地址 | to="/a" 或 :to="{ name: 'user', params: { id: 1 } }" |
replace |
导航时使用 router.replace() |
<router-link replace> |
custom |
自定义渲染,结合插槽使用 | <router-link custom v-slot="{ href }"> |
active-class |
链接激活时应用的 Class | 'active' |
exact-active-class |
链接完全匹配时应用的 Class | 'exact' |
七、<router-view> 属性
| 属性 | 用途 | 示例 |
|---|---|---|
name |
用于多视图 (命名视图) 渲染 | <router-view name="left"> |
route |
(高级) 强制指定要渲染的路由对象 | <router-view :route="someRoute"> |
八、Route (当前路由对象)
该对象通过 useRoute() 或 this.$route 获取。
| 字段 | 类型 | 含义 | 示例 |
|---|---|---|---|
params |
object |
动态路径参数 | route.params.id |
query |
object |
URL 查询参数 | route.query.q |
hash |
string |
URL 中的哈希值 (带 #) |
route.hash |
fullPath |
string |
完整的解析后路径 (含查询和哈希) | /user/1?x=1 |
name |
string |
当前路由的命名 | 'User' |
path |
string |
当前路径 (不含查询和哈希) | /user/1 |
meta |
object |
路由配置中的 meta 信息 |
route.meta.auth |
matched |
RouteRecord[] |
路由匹配到的所有记录 (用于嵌套路由) | route.matched |
九、组合式 API (Composition API)
| API | 用途 | 示例 |
|---|---|---|
useRoute() |
获取当前路由对象 (Route) |
const route = useRoute() |
useRouter() |
获取路由实例 (Router) |
const router = useRouter() |
十、编程式导航 (完整示例)
| 用途 | 示例 | 备注 |
|---|---|---|
| 命名路由跳转 | router.push({ name:'User', params:{ id:10 } }) |
推荐方式,不依赖路径顺序 |
| 带 Query 参数跳转 | router.push({ path:'/search', query:{ q:'x' } }) |
路径 + 查询参数 |
| 可等待的 Push/Replace | await router.push('/a') |
导航是异步的,可等待其完成 |
| URL 对象跳转 | router.push({ path: '/foo', hash: '#bar' }) |
完整控制 URL 细节 |
