Vue Router3
1.动态路由匹配
动态路径参数 以冒号开头
设置单个参数
// 路由配置
{
path: '/user/:id',
name:'user'
component: User
}
// 跳转匹配路由
this.$router.push('/user/8'); // 第一种方式
this.$router.push({ name: 'user', params: { id: 8 } }); // 第二种方式
// 获取方式
this.$route.params
// 输出结果
{id: '8'}
也可以设置多个参数
// 路由配置
{
path: '/user/:id/:type',
name:'user'
component: User
}
// 跳转匹配路由
this.$router.push('/user/8/one');
this.$router.push({ name: 'user', params: { id: 8,type:'one' } });
// 获取方式
this.$route.params
// 输出结果
{id: '8', type: 'one'}
2.嵌套路由
要在页面嵌套别的组件,需要配置父路由的children属性,在父页面添加 router-view
占位符
当路径为 /nestRoute/zhangsan
时候加载 zhangsan
的组件,/nestRoute/lisi
加载 lisi
组件
const router = new VueRouter({
routes: [
{
path: '/nestRoute',
component: nestRoute,
children: [
{
path: 'zhangsan',
component: zhangsan
},
{
path: 'lisi',
component: lisi
}
]
}
]
})
注意:以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
3.编程式的导航
router、routes、route的区别
1、router:路由器对象(new的路由器对象),包含一些操作路由的功能函数,来实现编程式导航。一般指的是在任何组件内访问路由。如:路由编程式导航的$router.push()
2、routes:指创建vue-router
路由实例的配置项。用来配置多个route
路由对象
3、route:指路由对象表示当前激活的路由的状态信息。如:this.$route
指的是当前路由对象,path/meta/query/params
声明式导航
router-link 会生成a标签
router-link 等同于router.push()
编程式导航
一、this.$router.replace()
它不会向 history 添加新记录,不能后退
二、this.$router.push()
这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:
字符串
router.push('home')对象
router.push({ path: 'home' })命名的路由 router里面配置的name名字 params 动态路径参数,以冒号开头 ,如果路由里面配置了/user/:userId 在地址栏显示,如果不配置不在地址栏显示,在页面也可以使用params拿到传过来的参数
router.push({ name: 'user', params: { userId: '123' }})带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意:如果提供了 path,params 会被忽略
const userId = '123'
router.push({ name: 'user', params: { userId }}) ====> /user/123
router.push({ path: `/user/${userId}` }) ====> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) ====> /user
同样的规则也适用于 router-link 组件的 to 属性。
router.go
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
操作 History
你也许注意到 router.push、 router.replace 和 router.go 跟
window.history.pushState、 window.history.replaceState 和 window.history.go (opens new window)好像,实际上它们确实是效仿 window.history API 的。
因此,如果你已经熟悉 Browser History APIs (opens new window),那么在 Vue Router 中操作 history 就是超级简单的。
还有值得提及的,Vue Router 的导航方法 (push、 replace、 go) 在各类路由模式 (history、 hash 和 abstract) 下表现一致。
4.命名路由
有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在 routes 配置中给路由设置name属性。
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
}
]
})
要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象:
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
这跟代码调用 router.push() 是一回事:
router.push({ name: 'user', params: { userId: 123 } })
5.命名视图
同级展示多个视图,而不是嵌套展示。例如:企业官网header、content、footer 三个视图,这个时候命名视图就派上用场了。如果router-view 没有设置名字,那么默认为default
<router-view class="head"></router-view>
<router-view class="cont" name="content"></router-view>
<router-view class="foot" name="footer"></router-view>
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s):
const router = new VueRouter({
routes: [
{
path: 'website',
components: {
default: () => import('@/views/vue/route/nameView/header'),
content: () => import('@/views/vue/route/nameView/content'),
footer: () => import('@/views/vue/route/nameView/footer')
}
}
]
})
嵌套命名视图
我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 router-view 组件。我们以一个设置面板为例:
/settings/emails /settings/profile
+-----------------------------------+ +------------------------------+
| UserSettings | | UserSettings |
| +-----+-------------------------+ | | +-----+--------------------+ |
| | Nav | UserEmailsSubscriptions | | +------------> | | Nav | UserProfile | |
| | +-------------------------+ | | | +--------------------+ |
| | | | | | | | UserProfilePreview | |
| +-----+-------------------------+ | | +-----+--------------------+ |
+-----------------------------------+ +------------------------------+
//嵌套命名视图
<div>
<h1>User Settings</h1>
<NavBar/>
<router-view/>
<router-view name="helper"/>
</div>
{
path: '/settings',
// 你也可以在顶级路由就配置命名视图
component: UserSettings,
children: [{
path: 'emails',
component: UserEmailsSubscriptions
}, {
path: 'profile',
components: {
default: UserProfile,
helper: UserProfilePreview
}
}]
}
6.重定向和别名
重定向
重定向也是通过 routes 配置来完成,下面例子是从 /a 重定向到 /b:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})
重定向的目标也可以是一个命名的路由:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: { name: 'foo' }}
]
})
甚至是一个方法,动态返回重定向目标:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: to => {
// 方法接收 目标路由 作为参数
// return 重定向的 字符串路径/路径对象
const { hash, query, params } = to
if(hash=='') return {name:'',hash:''}
if(query=='') return {path:'',query:null}
if(params=='') return {'/a/:id'}
else return {'/a'}
}}
]
})
别名
/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。
const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})
“别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。
7.通过props传参
// 路由配置
{
path: '/routeParam/:id',
name: 'RouteParam',
component: () => import('@/views/vue/route/routeParam'),
meta: { title: '路由组件传参' },
// props: true, 布尔模式
// props: { name: 'zhangsan'} 对象模式
props: (route) => ({ //函数模式
name: 'zhangsan',
id: route.params.id,
// hh:route.query.id
})
},
正常传参
$router.push({ name: 'RouteParam', params: { id: 333 } })
通过 this.$route.params 获取参数
通过布尔模式传参
通过 props 解耦,在路由中设置 props:true,在页面中添加props: ['id'],在页面直接获取id就行
对于包含命名视图的路由,你必须分别为每个命名视图添加 props
选项:
路径 path: '/routeParam/:id',
$router.push('/routeParam/666')
获取直接使用 {{ id }}
对象模式
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。
const router = new VueRouter({
routes: [
{
path: '/routeParam/:id',
component: Promotion,
props: { name: 'zhangsan' }
}
]
})
export default {
props: ['id', 'name'],
};
页面直接使用 {{name}} 获取参数
函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。
const router = new VueRouter({
routes: [
{
path: '/search',
component: SearchUser,
props: route => ({ query: route.query.q })
}
]
})
获取方式 通过 {{ name }}
export default {
props: ['id', 'name','hh'],
}
8.导航守卫
全局前置守卫
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
router.beforeEach((to, from, next) => {
console.log(to);
console.log(from);
next()
})
to: 即将要进入的目标 路由对象
from: 当前导航正要离开的路由
next: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数
全局解析守卫
在 2.5.0+ 你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
全局后置钩子
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {
// ...
})
路由独享的守卫
在路由配置上直接定义 beforeEnter 守卫:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
这些守卫与全局前置守卫的方法参数是一样的。
组件内的守卫
可以在组件中定义守卫,可以在路由组件内直接定义以下路由导航守卫:
beforeRouteEnter
beforeRouteUpdate (2.2 新增)
beforeRouteLeave
export default {
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
},
};
完整的导航解析流程
1、导航被触发。
2、在失活的组件里调用 beforeRouteLeave 守卫。
3、调用全局的 beforeEach 守卫。
4、在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
5、在路由配置里调用 beforeEnter。
6、解析异步路由组件。
7、在被激活的组件里调用 beforeRouteEnter。
8、调用全局的 beforeResolve 守卫 (2.5+)。
9、导航被确认。
10、调用全局的 afterEach 钩子。
11、触发 DOM 更新。
12、调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
9.路由元信息
定义路由的时候可以配置 meta 字段:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
children: [
{
path: 'bar',
component: Bar,
// a meta field
meta: { requiresAuth: true }
}
]
}
]
})
routes 配置中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录
例如,根据上面的路由配置,/foo/bar 这个 URL 将会匹配父路由记录以及子路由记录。
一个路由匹配到的所有路由记录会暴露为 route.matched 数组。因此,我们需要遍历 $route.matched 来检查路由记录中的 meta 字段。
在全局导航守卫中检查元字段:
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!auth.loggedIn()) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // 确保一定要调用 next()
}
})
10.过渡动效
单个路由的过渡
<transition name="slide-right">
<router-view></router-view>
</transition>
// 添加样式
.slide-left-enter, .slide-right-leave-to {
opacity: 0;
transform: translateX(100%)
}
.slide-left-leave-to, .slide-right-enter {
opacity: 0;
transform: translateX(-100%)
}
.slide-left-enter-active, .slide-left-leave-active, .slide-right-enter-active, .slide-right-leave-active {
transition: 1.5s;
position: absolute;
top:0;
}
11.数据获取
有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,你需要从服务器获取用户的数据。我们可以通过两种方式来实现:
1、导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。
当你使用这种方式时,我们会马上导航和渲染组件,然后在组件的 created 钩子中获取数据。这让我们有机会在数据获取期间展示一个 loading 状态,还可以在不同视图间展示不同的 loading 状态。
2、导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。从技术角度讲,两种方式都不错 —— 就看你想要的用户体验是哪种。
通过这种方式,我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter 守卫中获取数据,当数据获取成功后只调用 next 方法。
12.滚动行为
只有在全局下才可以起作用,body有滚动条才可以,
scrollBehavior(to, from, savedPosition) {
// return 期望滚动到哪个的位置
console.log(savedPosition);
return {y:200}
}
13.捕获所有路由或 404 Not found 路由
匹配所有路径
{ path: '*', redirect: '/404', hidden: true }
匹配以 `/user-` 开头的任意路径
{ path: '/user-*', redirect: '/404', hidden: true }
注意:通配符的路由应该放在最后
当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:
给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch ===> 'admin'
给出一个路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch ===> '/non-existing'
14. 路由组件传参的方式(总结)
通过 params 传递
路由配置
const routes = [
// 动态段以冒号开始
{ path: 'details/:id', name: "details", component: Details },
]
传参方式
// 字符串路径
this.$router.push('/details/001')
// 带有路径的对象
this.$router.push({path: '/details/001'})
// 命名路由,路由配置时,需要 name 字段
this.$router.push({ name: 'details', params: { id: '001' } })
// 注意,如果提供了 path,params 会被忽略:`params` 不能与 `path` 一起使用
router.push({ path: '/details', params: { id: '001' } }) // -> /details
获取方式
this.$route.params
通过 query 传递
这种情况下 query (查询参数)传递的参数会显示在 url 后面,如:/details/001?kind=car。
路由配置
const routes = [
{ path: 'details/:id', name: "details", component: Details },
]
传参方式
// 使用 query 时,以下三种方式都是可行的:
this.$router.push('/details/001?kind=car')
this.$router.push({ path: '/details/001', query: { kind: "car" }})
this.$router.push({ name: 'details', params: { id: '001' }, query: { kind: 'car' }})
获取方式
this.$route.query
通过 hash 传递
通过此方式,url 路径中带有 hash,例如:/details/001#car。
路由配置
const routes = [
{ path: 'details/:id', name: "details", component: Details },
]
传参方式
// 使用 hash 时,以下三种方式都是可行的(同 query):
this.$router.push('/details/001#car')
this.$router.push({ path: '/details/001', hash: '#car'})
this.$router.push({ name: 'details', params: { id: '001' }, hash: 'car'})
获取方式
$route.hash.slice(1)
通过 props 传递
在组件中使用 $route 会与路由紧密耦合,这限制了组件的灵活性,因为它只能用于特定的 URL。虽然这不一定是件坏事,但我们可以通过 props 配置来解除这种行为。
以解耦的方式使用 props 进行参数传递,主要是在路由配置中进行操作。
- 布尔模式
当 props 设置为 true 时,route.params 将被设置为组件的 props。
路由配置中,增加 props 字段,并将值 设置为 true
const User = {
props: ['id'], // 组件中通过 props 获取 id
template: '<div>User {{ id }}</div>'
}
const routes = [{ path: '/user/:id', component: User, props: true }]
注意:对于有命名视图的路由,你必须为每个命名视图定义 props 配置:
const routes = [
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
// 为 User 提供 props
props: { default: true, sidebar: false }
}
]
- 对象模式
当 props 是一个对象时,它将原样设置为组件 props。当 props 是静态的时候很有用。
路由配置
const routes = [
{
path: '/hello',
component: Hello,
props: { name: 'World' }
}
]
组件中获取数据
const Hello = {
props: {
name: {
type: String,
default: 'Vue'
}
},
template: '<div> Hello {{ name }}</div>'
}
<Hello /> 组件默认显示 Hello Vue,但路由配置了 props 对象,当路由跳转到 /hello 时,会显示传递过来的 name, 页面会显示为 Hello World。
- 函数模式
可以创建一个返回 props 的函数。这允许你将参数转换为其他类型,将静态值与基于路由的值相结合等等。
使用函数模式时,返回 props 的函数接受的参数为路由记录 route。
路由配置
// 创建一个返回 props 的函数
const dynamicPropsFn = (route) => {
return { name: route.query.say + "!" }
}
const routes = [
{
path: '/hello',
component: Hello,
props: dynamicPropsFn
}
]
组件获取数据
// 当 URL 为 /hello?say=World 时, 将传递 {name: 'World!'} 作为 props 传给 Hello 组件。
const Hello = {
props: {
name: {
type: String,
default: 'Vue'
}
},
template: '<div> Hello {{ name }}</div>'
}
注意:请尽可能保持 props 函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义 props,请使用包装组件,这样 vue 才可以对状态变化做出反应。
通过 Vuex 进行传递
store 存储状态
A 组件更改 store 中的状态
B 组件从 store 中获取
通过前端本地存储等方式
Local Storage;
Session Storage;
IndexedDB;
Web SQL;
Cookies。
Vue Router4
1.index.js
3.x的写法
这种写法是比较通用的,配置的是动态路由,前台只配置常用的几个即可。
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [{
path: '/',
name: '首页',
component: () =>
import( /* webpackChunkName: "page" */ '@/views/index'),
meta: {
requireAuth: true,
},
children: [{
path: '/index',
name: '首页',
component: () =>
import( /* webpackChunkName: "page" */ '@/views/wel'),
meta: {
requireAuth: true,
}
}]
}]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
4.x的写法
导入createRouter, createWebHistory这两个方法,使用createWebHistory方法创建一个routerHistory对象,使用 createRouter 创建路由器。
import { createRouter, createWebHistory } from "vue-router";
import login from "../views/login.vue";
import index from "../views/index.vue";
const routes = [
{
path: "/login",
name: "登录",
component: login,
meta: {
requireAuth: false,
},
}, {
path: "/",
name: "首页",
component: index,
meta: {
requireAuth: true,
},
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
});
export default router;
2.创建方式
3.x的写法
import VueRouter from "vue-router"'
const router = new VueRouter({
// options
......
})
4.x的写法
import { createRouter } from "vue-router"
const router = createRouter({
// opyions.....
})
3.路由模式
3.x的写法
const router = new VueRouter({
mode: 'hash' / 'history'
})
4.x的写法
import {createRouter, createWebHashHistory,createWebHashHistory} from 'vue-router'
const router = createRouter({
history:createWebHashHistory() / createWebHashHistory()
})
4.动态路由匹配
3.x的写法
{ path: '*',component: 404page }
4.x的写法
// 将匹配所有内容并将其放在 `$route.params.pathMatch` 下
{ path:'/:pathMatch(.*)*',component: NotFound },
// 将匹配以 `/user-` 开头的所有内容,并将其放在 `$route.params.afterUser` 下
{ path: '/user-:afterUser(.*)', component: UserGeneric },
使用以前的*语法会报错,也无法解析到任意路径上。
5.重定向
3.x的写法
{
path: '*',
redirect: Home
}
4.x的写法
{
path: '/:pathMatch(.*)*', // 需要使用正则去匹配
redirect: Home,
}
6.挂载方式
3.x的写法
import router from './router.js'
new Vue({
router
})
4.x的写法
import { createApp } from 'vue'import router from './router.js'
import App from './App.vue'
createApp(App).use(router).mount('#app');
7.件中的使用
3.x的写法
export default({
methods:{
linkToHome(){
this.$router.push({path:'/' })
}
}
})
4.x的写法
因为setup中不能访 this,所以提供两个api来获取 router 和 route , useRouter() 和 useRoute()
import { useRouter,useRoute } from "vue-router"
export default({
setup(){
const router = useRouter();
const route = useRoute();
const linkToHome = () => {
router.push({path:'/'})
}
return{ linkToHome }
}
})
8.导航守卫
由于 vue3 composition api的原因,beforeRouteUpdate 和 beforeRouteLeave被替换为 onBeforeRouteUpdate 和 onBeforeRouteLeave
9.路由的匹配语法
在参数中自定义正则
当定义像 :userId 这样的参数时,我们内部使用以下的正则 ([^/]+) (至少有一个字符不是斜杠 / )来从 URL 中提取参数。这很好用,除非你需要根据参数的内容来区分两个路由。想象一下,两个路由 /:orderId 和 /:productName,两者会匹配完全相同的 URL,所以我们需要一种方法来区分它们。最简单的方法就是在路径中添加一个静态部分来区分它们:
const routes = [
// 匹配 /o/3549
{ path: '/o/:orderId' },
// 匹配 /p/books
{ path: '/p/:productName' },
]
但在某些情况下,我们并不想添加静态的 /o /p 部分。由于,orderId 总是一个数字,而 productName 可以是任何东西,所以我们可以在括号中为参数指定一个自定义的正则:
const routes = [
// /:orderId -> 仅匹配数字
{ path: '/:orderId(\\d+)' },
// /:productName -> 匹配其他任何内容
{ path: '/:productName' },
]
可重复的参数
如果你需要匹配具有多个部分的路由,如 /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*' },
]
这将为你提供一个参数数组,而不是一个字符串,并且在使用命名路由时也需要你传递一个数组:
// 给定 { path: '/:chapters*', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 产生 /
router.resolve({ name: 'chapters', params: { chapters: ['a', 'b'] } }).href
// 产生 /a/b
// 给定 { path: '/:chapters+', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 抛出错误,因为 `chapters` 为空
这些也可以通过在右括号后添加它们与自定义正则结合使用:
const routes = [
// 仅匹配数字
// 匹配 /1, /1/2, 等
{ path: '/:chapters(\\d+)+' },
// 匹配 /, /1, /1/2, 等
{ path: '/:chapters(\\d+)*' },
]
Sensitive 与 strict 路由配置
默认情况下,所有路由是不区分大小写的,并且能匹配带有或不带有尾部斜线的路由。例如,路由 /users 将匹配 /users、/users/、甚至 /Users/。这种行为可以通过 strict 和 sensitive 选项来修改,它们可以既可以应用在整个全局路由上,又可以应用于当前路由上:
const router = createRouter({
history: createWebHistory(),
routes: [
// 将匹配 /users/posva 而非:
// - /users/posva/ 当 strict: true
// - /Users/posva 当 sensitive: true
{ path: '/users/:id', sensitive: true },
// 将匹配 /users, /Users, 以及 /users/42 而非 /users/ 或 /users/42/
{ path: '/users/:id?' },
]
strict: true, // applies to all routes
})
可选参数
你也可以通过使用 ? 修饰符(0 个或 1 个)将一个参数标记为可选:
const routes = [
// 匹配 /users 和 /users/posva
{ path: '/users/:userId?' },
// 匹配 /users 和 /users/42
{ path: '/users/:userId(\\d+)?' },
]
请注意,* 在技术上也标志着一个参数是可选的,但 ? 参数不能重复。