Vue Router如何让全局catch-all路由也能捕获与定义路由部分匹配的无效URL
原因说明
这是Vue Router的默认匹配逻辑导致的:路由匹配会按定义顺序优先命中第一个符合规则的路由,/album/foo完全匹配/album/:album的路径规则,所以会直接进入Album组件,不会走到后续的catch-all路由。
方案1:路由独享守卫提前校验(通用度最高,适合所有场景)
直接在Album路由的配置中增加beforeEnter守卫,进入路由前先向Sanity发起查询校验对应相册是否存在,不存在则直接跳转404,无需挂载Album组件再做判断。
// 封装校验相册是否存在的公共方法 const validateAlbumExist = async (albumSlug) => { // 替换为你自己的Sanity查询逻辑 const album = await sanityClient.fetch(`*[_type == "album" && slug.current == $slug][0]`, { slug: albumSlug }) return !!album } const routes = [ { path: '/album/:album', name: 'album', component: Album, beforeEnter: async (to, from, next) => { const isAlbumExist = await validateAlbumExist(to.params.album) if (isAlbumExist) { next() } else { // 不存在则直接跳转至404路由 next({ name: 'NotFound' }) } } }, { path: '/', name: 'home', component: Home, }, // 注意Vue Router 4的catch-all路由需要用该写法,原有/*写法已废弃 { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound, }, ];
方案2:路由参数加正则约束(性能最优,适合相册命名有固定规则的场景)
如果你的相册slug有统一的格式规则,比如都是6位十六进制字符、纯数字ID等,可以直接在路由定义时给参数加上正则匹配规则,不符合规则的请求不会命中Album路由,自动走catch-all的404。
示例(相册slug为6位十六进制字符的场景):
{ path: '/album/:album([a-f0-9]{6})', name: 'album', component: Album, }
方案3:预注册所有合法相册路由(适合静态站点/SSG场景)
如果你的站点是静态生成、相册数量少且更新频率低,可以在应用初始化/构建阶段从Sanity拉取所有合法的相册slug,动态注册对应的路由,未注册的/album/xxx路径会直接命中404。
// 应用初始化时拉取所有合法相册slug const albumSlugs = await sanityClient.fetch(`*[_type == "album"].slug.current`) // 逐个注册合法的相册路由 albumSlugs.forEach(slug => { router.addRoute({ path: `/album/${slug}`, name: `album-${slug}`, component: Album }) }) // 最后注册catch-all路由 router.addRoute({ path: '/:pathMatch(.*)*', component: NotFound })
内容的提问来源于stack exchange,提问作者Kevin Britten
相关产品推荐
相关产品推荐

