Vue Router
安装
1
npm install vue-router
基本使用
创建路由实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createRouter, createWebHistory } from 'vue-router';
import HomeView from '@/views/HomeView.vue';
import AboutView from '@/views/AboutView.vue';
// 配置路由
const routes = [
{ path: '/', component: HomeView },
{ path: '/about', component: AboutView },
];
// 创建路由实例
const router = createRouter({
history: createWebHistory(), // HTML5模式
routes, // 路由配置
});
export default router;
注册路由插件
1
2
3
4
5
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
createApp(App).use(router).mount('#app'); // use() 需要在 mount() 之前调用
插件的功能有:
- 全局注册
RouterView
和RouterLink
组件。 - 添加全局
$router
和$route
属性。 - 启用
useRouter()
和useRoute()
组合式函数。 - 触发路由器解析初始路由。
使用路由
1
2
3
4
5
6
7
8
9
10
11
12
<template>
<p><strong>当前路由路径为</strong> {{ $route.fullPath }}</p>
<!-- 导航区 -->
<nav>
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</nav>
<!-- 主体区 -->
<main>
<router-view />
</main>
</template>
使用 router-link
组件创建链接,使得 Vue Router 能够在不重新加载页面的情况下改变 URL,处理 URL 的生成、编码和其他功能。
RouterView
组件可以使 Vue Router 知道你想要在哪里渲染当前 URL 路径对应的路由组件。它需要在某处被导入,否则 Vue Router 就不会渲染任何东西。
注意
- 路由组件通常存放在
pages
或views
文件夹,一般组件通常存放在components
文件夹。- 通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。
不同的历史模式
在创建路由器实例时,history
配置允许我们在不同的历史模式中进行选择。
Hash 模式
- 优点:兼容性更好,因为不需要服务器端处理路径。
- 缺点:URL 带有
#
不太美观,且在 SEO 优化方面相对较差。如:https://example.com/#/user/id
1
2
3
4
5
6
7
8
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
routes: [
//...
],
})
HTML5 模式
- 优点:URL 更加美观,不带有
#
,更接近传统的网站 URL。如:https://example.com/user/id
- 缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有
404
错误。
1
2
3
4
5
6
7
8
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
//...
],
})
to的两种写法
1
2
3
4
5
<!-- 第一种:to的字符串写法 -->
<router-link active-class="active" to="/home">主页</router-link>
<!-- 第二种:to的对象写法 -->
<router-link active-class="active" :to="{path:'/home'}">Home</router-link>
嵌套路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default createRouter({
history: createWebHistory(),
routes: [
{
path: '/users/:username',
component: User,
children: [
{ path: '', component: UserHome }, // User 组件的默认子路由
{ path: 'profile', component: UserProfile },
{ path: 'posts', component: UserPosts },
],
},
],
});
注意,以
/
开头的嵌套路径将被视为根路径。嵌套的子路由不能/
开头
命名路由
当创建一个路由时,可以选择给路由一个 name
:
1
2
3
4
5
6
7
const routes = [
{
path: '/user/:username',
name: 'profile',
component: User
}
]
然后可以使用 name
而不是 path
来传递 to
属性给 <router-link>
:
1
2
3
<router-link :to="{ name: 'profile', params: { username: 'xiaowhang' } }">
User profile
</router-link>
优点
- 没有硬编码的 URL。
params
的自动编码/解码。- 防止你在 URL 中出现打字错误。
- 绕过路径排序,例如展示一个匹配相同路径但排序较低的路由。
注意
所有路由的命名都必须是唯一的。如果为多条路由添加相同的命名,路由器只会保留最后那一条。
路由组件传参
query参数
传递参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 跳转并携带query参数(to的字符串写法) -->
<router-link to="/users?id=xiaowhang&b=2">跳转</router-link>
<!-- 跳转并携带query参数(to的对象写法) -->
<router-link
:to="{
// name:'user', // 用name也可以跳转
path: '/users',
query: { id: 'xiaowhang', b: 2 },
}"
>
跳转
</router-link>
接收参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>{{ $route.query }}</div>
</template>
<!-- 或者 -->
<template>
<div>{{ route.query }}</div>
</template>
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
</script>
params参数
传递参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!--
routes: [{
path: '/users/:username/:b',
component: User,
},
],
-->
<!-- 跳转并携带params参数(to的字符串写法) -->
<router-link to="/users/xiaowhang/2">跳转</router-link>
<!-- 跳转并携带params参数(to的对象写法) -->
<router-link
:to="{
name:'user',
params: { id: 'xiaowhang', b: 2 },
}"
>
跳转
</router-link>
接收参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>{{ $route.params }}</div>
</template>
<!-- 或者 -->
<template>
<div>{{ route.params }}</div>
</template>
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
</script>
注意
- 传递
params
参数时,若使用to
的对象写法,必须使用name
配置项,不能用path
。- 传递
params
参数时,需要提前在规则中占位。
将 props 传递给路由组件
作用:让路由组件更方便的收到参数(可以将路由参数作为props
传给组件)
1
2
3
4
5
6
7
8
9
10
11
12
13
{
name: 'user',
path: '/users/:id/:b',
component: User,
// 布尔模式,作用:把收到了每一组params参数,作为props传给Detail组件
props: true,
// 对象模式,作用:把对象中的每一组key-value作为props传给Detail组件
// props: { id: xiaowhang, b: 2, c: 3 },
// 函数模式,作用:把返回的对象中每一组key-value作为props传给Detail组件
// props: route => route.query,
},
1
2
3
4
5
6
7
8
<template>
<div>{{ id }}</div>
<div>{{ b }}</div>
</template>
<script setup>
defineProps(['id', 'b']);
</script>
replace属性
作用:控制路由跳转时操作浏览器历史记录的模式。
浏览器的历史记录有两种写入方式:分别为
push
和replace
:push
是追加历史记录(默认值)。replace
是替换当前记录。
开启
replace
模式:1
<router-link :to="..." replace>News</router-link>
编程式导航
1
2
3
4
import { useRoute, useRouter } from 'vue-router';
const route = useRoute(); // 获取当前路由信息
const router = useRouter(); // 获取路由实例
导航到不同的位置
声明式 | 编程式 |
---|---|
<router-link :to="...">...</router-link> | router.push(...) |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 字符串路径
router.push('/users/xiaowhang')
// 带有路径的对象
router.push({ path: '/users/xiaowhang' })
// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'xiaowhang' } })
// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })
// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })
const username = 'xiaowhang'
// 我们可以手动建立 url,但我们必须自己处理编码
router.push(`/user/${username}`) // -> /user/xiaowhang
// 同样
router.push({ path: `/user/${username}` }) // -> /user/xiaowhang
// 如果可能的话,使用 `name` 和 `params` 从自动 URL 编码中获益
router.push({ name: 'user', params: { username } }) // -> /user/xiaowhang
// `params` 不能与 `path` 一起使用
router.push({ path: '/user', params: { username } }) // -> /user
替换当前位置
声明式 | 编程式 |
---|---|
<router-link :to="..." replace>...</router-link> | router.replace(...) |
也可以直接在传递给 router.push
的 to
参数中增加一个属性 replace: true
:
1
2
3
router.push({ path: '/home', replace: true })
// 相当于
router.replace({ path: '/home' })
横跨历史
1
2
3
4
5
6
7
8
9
10
11
12
// 向前移动一条记录,与 router.forward() 相同
router.go(1)
// 返回一条记录,与 router.back() 相同
router.go(-1)
// 前进 3 条记录
router.go(3)
// 如果没有那么多记录,静默失败
router.go(-100)
router.go(100)
重定向
作用:将特定的路径,重新定向到已有路由。
从 /
重定向到 /home
:
1
const routes = [{ path: '/', redirect: '/home' }]
重定向的目标也可以是一个命名的路由:
1
const routes = [{ path: '/', redirect: { name: 'homepage' } }]
也可以是一个方法,动态返回重定向目标:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const routes = [
{
// /search/screens -> /search?q=screens
path: '/search/:searchText',
redirect: to => {
// 方法接收目标路由作为参数
// return 重定向的字符串路径/路径对象
return { path: '/search', query: { q: to.params.searchText } }
},
},
{
path: '/search',
// ...
},
]
相对重定向
1
2
3
4
5
6
7
8
9
10
11
12
const routes = [
{
// 将总是把/users/123/posts重定向到/users/123/profile。
path: '/users/:id/posts',
redirect: to => {
// 该函数接收目标路由作为参数
// 相对位置不以`/`开头
// 或 { path: 'profile'}
return 'profile'
},
},
]
命名视图
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar
(侧导航) 和 main
(主内容) 两个视图。
1
2
3
4
<template>
<router-view class="view sidebar" name="Sidebar" />
<router-view class="view main-content" />
</template>
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components
配置 (带上 s):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
components: {
// 它们与 `<router-view>` 上的 `name` 属性匹配
default: Home,
// Sidebar: Sidebar 的缩写
Sidebar,
},
},
],
});
Vue Router
http://xiaowhang.github.io/archives/1237244176/