Vue Router
是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。
本章只做学习记录,详尽的内容一定要去官网查看api文档 Vue Router-Vue.js 的官方路由
1. 路由的基本使用
1.1 安装vue-router
npm install vue-router@4
1.2 使用vue-router
1、src下创建一个叫 router 的文件夹,并创建 index.js,创建并暴露一个路由器 router
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '@/components/Home.vue'
import About from '@/components/About.vue'
// 1. 定义一些路由
// 每个路由都需要映射到一个组件。
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
]
// 2. 创建路由实例并传递 `routes` 配置
const router = createRouter({
// 2. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
export default router
2、创建需要的组件
3、在 main.js 中导入并 use router
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
//创建实例,使用 router,并挂载根实例
createApp(App).use(router).mount('#app')
4、App.vue 中使用路由
<template>
<h1>Hello Vue-Route!</h1>
<p>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<router-link to="/">Go to Home</router-link> |
<router-link to="/about">Go to About</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</template>
<script>
export default {
name: 'App',
components: {}
}
</script>
<style>
...
}
</style>
router-view
将显示与 url 对应的组件。你可以把它放在任何地方,以适应你的布局。
5、测试
点击 “Go to Home”,显示“this is home”
点击 “Go to About”,显示“this is about”
2. 动态路由匹配
很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如:/user/12
和 /user/13
映射到同一个组件。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数
。
1、App.vue 使用路由
<template>
<h1>Hello Vue-Route!</h1>
<p>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<router-link to="/">Go to Home</router-link> |
<router-link to="/about">Go to About</router-link>
<router-link to="/user/12"> 12号用户 </router-link>
<router-link to="/user/13"> 13号用户 </router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</template>
...
2、router/index.js 新增动态路由映射
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '@/components/Home.vue'
import About from '@/components/About.vue'
import User from '@/components/User.vue'
// 1. 定义一些路由
// 每个路由都需要映射到一个组件。
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/user/:id', component: User }
]
...
路径参数
用冒号:
表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params
的形式暴露出来。因此,我们可以通过更新 User 的模板来呈现当前的用户 ID:
3、User 组件
<template>
My id is {{ $route.params.id }}
</template>
4、测试
点击 “12号用户”,显示“My id is 12”
点击 “13号用户”,显示“My id is 13”
注: 你可以在同一个路由中设置有多个路径参数
,它们会映射到 $route.params
上的相应字段。例如:
匹配模式 | 匹配路径 | $route.params |
---|---|---|
/users/:username | /users/eduardo | { username: ‘eduardo’ } |
/users/:username/posts/:postId | /users/eduardo/posts/123 | { username: ‘eduardo’, postId: ‘123’ } |
除了 $route.params
之外,$route
对象还公开了其他有用的信息,如 $route.query
(如果 URL 中存在参数)、$route.hash
等。
3. 路由的匹配语法
3.1 参数中自定义正则
当定义像 :userId
这样的参数时,我们内部可以使用正则表达进行修饰。
const routes = [
// /:orderId -> 仅匹配数字
{ path: '/:orderId(\\d+)', component: component1},
// /:productName -> 匹配其他任何内容
{ path: '/:productName', component: component2},
]
现在,转到 /25
将匹配 /:orderId
,其他情况将会匹配 /:productName
。routes 数组的顺序并不重要!
3.2 参数数组
如果你需要匹配具有多个部分的路由,如 /first/second/third
,你应该用 *
(0 个或多个)和 +
(1 个或多个)将参数标记为可重复:
const routes = [
// /:chapters -> 匹配 /one, /one/two, /one/two/three, 等
{ path: '/:chapters+' },
// /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等
{ path: '/:chapters*' },
]
这将为你提供一个参数数组
,而不是一个字符串,并且在使用命名路由时也需要你传递一个数组:
1、router/index.js 新增动态路由映射:
const routes = [
...
{ path: '/user/:id*', component: User }
]
2、App.vue 使用路由
<router-link to="/user/11/22/33"> 参数数组 </router-link>
3、测试
点击 “参数数组”,显示“My id is [ “11”, “22”, “33” ]”
4. 嵌套路由
一些应用程序的 UI 由多层嵌套的组件组成。例如:/user/johnny/profile
、/user/johnny/posts
中,profile、posts 属于 johnny 下属 url,可以配置嵌套路由
来表达这种关系。
我们上述案例中的 <router-view>
是一个顶层的 router-view
。它渲染顶层路由匹配的组件。同样地,一个被渲染的组件也可以包含自己嵌套的 <router-view>
。例如,如果我们在 User
组件的模板内添加一个 <router-view>
。
1、User 组件添加<router-view>
<template>
My id is {{ $route.params.id }}
<p>
<router-link to="/user/12/profile">头像</router-link> |
<router-link to="/user/12/posts">岗位</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</template>
2、router/index.js 新增子路由映射
要将组件渲染到这个嵌套的 router-view 中,我们需要在路由中配置 children
:
...
import User from '@/components/user'
import UserProfile from '@/components/user/UserProfile.vue'
import UserPosts from '@/components/user/UserPosts.vue'
// 1. 定义一些路由
// 每个路由都需要映射到一个组件。
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{
path: '/user/:id',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: 'posts',
component: UserPosts,
},
]
}
]
...
children
配置只是另一个路由数组
,就像 routes
本身一样。因此,你可以根据自己的需要,不断地嵌套视图。
3、子组件
4、测试
点击 “头像”
点击 “岗位”
嵌套路由传参
上述案例有个问题,User 组件的访问路径是写死的 <router-link to="/user/12/profile">头像</router-link>
,我们可以通过 v-bind
动态获取上层的路径参数。
<template>
My id is {{ $route.params.id }}
<p>
<router-link :to=" '/user/' + $route.params.id + '/profile' ">头像</router-link> |
<router-link :to=" '/user/' + $route.params.id + '/posts' ">岗位</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</template>
5. 路由命名
除了 path
之外,你还可以为任何路由提供 name
。
router/index.js :
const routes = [
{
path: '/', name: 'home', component: Home
},
{
path: '/about', name: 'about', component: About
},
{
path: '/user/:id',
name: 'user',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: 'posts',
component: UserPosts,
},
]
}
]
为路由路径命名。
App.vue:
<template>
<h1>Hello Vue-Route!</h1>
<p>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<!-- <router-link to="/">Go to Home</router-link> | -->
<router-link :to="{name: 'home'}">Go to Home</router-link> |
<router-link :to="{name: 'about'}">Go to About</router-link> |
<router-link :to="{name: 'user', params: {id: 12}}"> 12号用户 </router-link> |
<router-link :to="{name: 'user', params: {id: 13}}"> 13号用户 </router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</template>
要链接到一个命名的路由,可以向 router-link
组件的 to
属性传递一个对象,路径参数
通过 params
传递。
6. 视图命名
有时候想同时 (同级) 展示多个视图,例如创建一个布局,有 sidebar
(侧导航) 和 main
(主内容) 两个视图,这个时候命名视图就派上用场了。如果 router-view
没有设置名字,那么默认为 default
。
App.vue:
<template>
...
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view name="LeftSidebar"></router-view> |
<router-view></router-view> |
<router-view name="RightSidebar"></router-view>
</template>
router/index.js :
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components
配置 (带上 s):
const routes = [
{
path: '/', name: 'home', component: Home
},
{
path: '/about',
name: 'about',
//component: About
components: {
LeftSidebar: UserProfile,
default: About,
RightSidebar: UserPosts
}
},
{
path: '/user/:id',
name: 'user',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: 'posts',
component: UserPosts,
},
]
}
]
设置 url=/about
的视图 LeftSidebar
的加载组件为 UserProfile
,视图 default
的加载组件为 About
,视图 RightSidebar
的加载组件为 UserPosts
。
测试:
点击 “Go to Home”
点击 “Go to About”
7. 编程式导航
除了使用 <router-link>
创建 a 标签来定义导航链接,我们还可以借助 router
的实例方法,通过编写代码来实现。
在 Vue 实例中,你可以通过 $router
访问路由实例。因此你可以调用 this.$router.push
。当你点击 <router-link>
时,内部会调用这个方法,所以点击 <router-link :to="...">
相当于调用 router.push(...)
。
声明式 | 编程式 |
---|---|
<router-link :to=“…”> | router.push(…) |
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:
// 字符串路径
router.push('/users/eduardo')
// 带有路径的对象
router.push({ path: '/users/eduardo' })
// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })
// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })
// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })
注意:如果提供了 path,params 会被忽略,上述例子中的 qu
App.vue:
<template>
<h1>Hello Vue-Route!</h1>
<p>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<!-- <router-link to="/">Go to Home</router-link> | -->
<router-link :to="{name: 'home'}">Go to Home</router-link> |
<router-link :to="{name: 'about'}">Go to About</router-link> |
<router-link :to="{name: 'user', params: {id: 12}}"> 12号用户 </router-link> |
<router-link :to="{name: 'user', params: {id: 13}}"> 13号用户 </router-link>
<button @click="tiaozhuan">push跳转</button>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</template>
<script>
export default {
name: 'App',
components: {},
methods: {
tiaozhuan(){
this.$router.push({
name: 'user',
params: {
id: 12
}
})
}
}
}
</script>
...
点击 “push跳转”,地址栏跳转到 http://localhost:8080/#/user/12
替换当前位置
它的作用类似于 router.push
,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。
声明式 | 编程式 |
---|---|
<router-link :to=“…” replace> | router.replace(…) |
8. 重定向和别名
通过 redirect
配置重定向
const routes = [{ path: '/home', component: Component, redirect: '/' }]
//重定向的目标也可以是一个命名的路由
const routes = [{ path: '/home', component: Component, redirect: { name: 'homepage' } }]
通过 alias
配置别名
const routes = [{ path: '/', component: Homepage, alias: '/home' }]
9. 路由组件传参
在第二节提到动态路由匹配,通过 {{ $route.params.id }}
获取路径参数,这样会使得组件和路由紧密耦合,这限制了组件的灵活性。为了组件的灵活性,我们可以通过 props
配置来解耦
//路由 props: true route.params 将被传递给组件的 props
const routes = [{ path: '/user/:id', component: User, props: true }]
//组件 通过 props 指定传递的路径参数
const User = {
// 请确保添加一个与路由参数完全相同的 prop 名
props: ['id'],
template: '<div>User {{ id }}</div>'
}
1、router/index.js 路由器配置props:true
2、路由映射的组件通过 props 指定参数
3、测试
布尔模式
当 props
设置为 true
时,route.params
将被设置为组件的 props
。
命名视图
对于有命名视图的路由,你必须为每个命名视图定义 props
配置:
const routes = [
{
path: '/user/:id',
components: { default: User, LeftSidebar: UserProfile },
props: { default: true, sidebar: false }
}
]
对象模式
当 props
是静态的时候很有用。
const routes = [
{
path: '/user/:id',
name: 'user',
component: User,
props: { id: 20 },
...
}
]
函数模式
你可以创建一个返回 props
的函数。
10. 不同的历史模式
Hash 模式
hash 模式是用 createWebHashHistory()
创建的,它在内部传递的实际 URL 之前使用了一个哈希字符(#
)
HTML5 模式
用 createWebHistory()
创建 HTML5 模式,推荐使用这个模式。需要服务器配置。