Vue Router (动态路由匹配)
前言:
动态路由:是指路由路径中包含变量部分(动态参数),可以根据不同的参数值渲染同一个组件,但展示不同的内容。
动态路由匹配:是指在路由路径(path)中定义可变的 URL 段(参数),使得同一个路由组件能够响应多个不同的 URL,根据不同的参数值渲染对应的内容。
1、基本用法
路径参数用冒号 : 表示。
我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染:
像 /users/zhangsan和 /users/lisi这样的 URL 都会映射到同一个路由。
import User from './User.vue'// 这些都会传递给 `createRouter`
const routes = [// 动态字段以冒号开始{ path: '/users/:id', component: User },
]通过更新 User 的模板来呈现当前的用户 ID:
<template><div><!-- 当前路由可以通过 $route 在模板中访问 -->User {{ $route.params.id }}</div>
</template>2、多个路径参数
定义:
在同一个路由中设置多个路径参数,它们会映射到 $route.params 上的相应字段。
示例:
对于路径 /users/zhangsan/posts/123,$route.params 将包含 { username: 'zhangsan', postId: '123' }。
const routes = [{ path: '/users/:username/posts/:postId', component: UserPosts },
]3、响应路由参数的变化
当用户从
/users/zhangsan导航到/users/lisi时,相同的组件实例将被重复使用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会被调用。
3.1 watch 监听$route 对象上的任意属性。
//组合式
<script setup>
import { watch } from 'vue'
import { useRoute } from 'vue-router'const route = useRoute()watch(() => route.params.id, (newId, oldId) => {// 对路由变化做出响应...
})
</script>//响应式
<script>
export default {created() {this.$watch(() => this.$route.params.id,(newId, oldId) => {// 对路由变化做出响应...})},
}
</script>3.2 使用 beforeRouteUpdate 导航守卫
//组合式
<script setup>
import { onBeforeRouteUpdate } from 'vue-router'
// ...onBeforeRouteUpdate(async (to, from) => {// 对路由变化做出响应...userData.value = await fetchUser(to.params.id)
})
</script>//响应式
<script>
export default {async beforeRouteUpdate(to, from) {// 对路由变化做出响应...this.userData = await fetchUser(to.params.id)},// ...
}
</script>4、捕获所有路由或 404 Not found 路由
const routes = [{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },{ path: '/user-:afterUser(.*)', component: UserGeneric },
]
path: '/:pathMatch(.*)*':这是一个 动态路由参数 + 通配符语法,是 Vue Router 4 推荐的“捕获所有路由”的写法。匹配任意路径(任意字符串),并将整个路径作为参数pathMatch的值
name: 'NotFound':给这个路由起了一个名字,叫'NotFound',你可以用它进行编程式导航,比如:router.push({ name: 'NotFound' })
component: NotFound:当这条路由匹配时,会渲染一个名为NotFound的 Vue 组件,通常是你自定义的 404 页面。
path: '/user-:afterUser(.*)':带有动态参数的路由路径。路径必须以/user-开头;-后面的所有内容会被捕获,作为动态参数afterUser的值;(.*)是一个 正则表达式片段,表示匹配任意字符(包括斜杠)零次或多次。
/user-anything-you-want
/user-profile/settings
/user-john
/user-123
:afterUser(.*)
:afterUser是一个动态路由参数的名字(.*)是一个 Vue Router 的动态路径匹配语法,表示“匹配任意字符序列(包括/)”它允许afterUser参数不仅包含普通字符,还可以包含 斜杠/,因此可以匹配类似/user-profile/details这样的路径。
component: UserGeneric
当匹配成功时,会渲染一个名为
UserGeneric的 Vue 组件;你可以在该组件中通过route.params.afterUser获取到动态参数的值。
5、高级匹配模式
Vue Router 使用自己的路径匹配语法,支持许多高级匹配模式,如可选的参数,零或多个 / 一个或多个,甚至自定义的正则匹配规则。
5.1 在参数中自定义正则
const routes = [// 只匹配数字 ID 的用户页{ path: '/user/:id(\\d+)', component: UserById },// 只匹配小写字母、数字和连字符的帖子页{ path: '/post/:slug([a-z0-9-]+)', component: PostDetail },// 只匹配类似 file.txt 格式的文件页{ path: '/file/:filename(\\w+\\.\\w+)', component: FileView },
]注意:在 JavaScript 的字符串中,反斜杠
\` 是转义字符,所以如果你要匹配一个真正的\d,你需要写成\\d。
5.2 可重复的参数
用
*(0 个或多个)和+(1 个或多个)将参数标记为可重复:
const routes = [// /:chapters -> 匹配 /one, /one/two, /one/two/three, 等{ path: '/:chapters+' },// /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等{ path: '/:chapters*' },
]5.3 Sensitive 与 strict 路由配置
默认情况下,所有路由是不区分大小写的,并且能匹配带有或不带有尾部斜线的路由。可以通过
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
})5.4 可选参数
使用
?修饰符(0 个或 1 个)将一个参数标记为可选:注意:
*在技术上也标志着一个参数是可选的,但?参数不能重复。
const routes = [// 匹配 /users 和 /users/posva{ path: '/users/:userId?' },// 匹配 /users 和 /users/42{ path: '/users/:userId(\\d+)?' },
]