Vue Router 的通配符路由无法捕获已匹配动态路径(如 /movie/:id)的非法参数,因其仍满足路由规则;真正有效的 404 处理需结合参数校验、服务端响应拦截与导航守卫协同实现。
vue router 的通配符路由无法捕获已匹配动态路径(如 `/movie/:id`)的非法参数,因其仍满足路由规则;真正有效的 404 处理需结合参数校验、服务端响应拦截与导航守卫协同实现。
在 Vue 3 单页应用中,/:pathMatch(.*)* 通配符路由虽能兜底未声明路径(如 /xyz),但对已定义的动态路由(如 /movie/:id)完全失效——只要 URL 形式符合 /movie/xxx,无论 xxx 是否为合法 ID,Router 都会优先匹配该路由记录,根本不会进入 404 分支。这是设计使然,而非配置错误。
通过正则限制 :id 必须为数字,避免无效参数进入组件:
// router/index.ts{ path: '/movie/:id(d+)', name: 'movie_details', component: MovieDetailsView, // 若访问 /movie/abc → 直接 404(Router 层拦截)}
⚠️ 注意:此方式仅适用于 ID 严格为纯数字的场景;若 TMDB ID 支持字母(如 tt1234567),则需退回到业务层判断。
在 MovieDetailsView.vue 的 onMounted 或 setup 中,调用 API 获取电影详情,并在请求失败时主动跳转:
立即学习“前端免费学习笔记(深入)”;
<!-- src/views/MovieDetailsView.vue --><script setup lang="ts">import { useRoute, useRouter } from 'vue-router'import { getMovieById } from '@/api/tmdb'import { onMounted } from 'vue'const route = useRoute()const router = useRouter()const movie = ref<any>(null)onMounted(async () => { try { movie.value = await getMovieById(route.params.id as string) } catch (err: any) { // 捕获 HTTP 404 或其他业务不存在状态 if (err.response?.status === 404 || err.code === 'NOT_FOUND') { await router.push({ name: '404' }) return } // 其他错误(网络异常等)可降级显示错误提示 console.error('Failed to load movie:', err) }})</script>
在路由守卫中补充兜底逻辑,防止遗漏:
// router/index.tsrouter.beforeEach(async (to, from, next) => { // 对所有带 :id 的路由,做前置参数格式快速校验(轻量) if (to.name && to.name.toString().includes('_details')) { const id = to.params.id as string if (!id || !/^[a-zA-Z0-9]+$/.test(id)) { return next({ name: '404' }) } } next()})
| 场景 | 是否应显示 404 |
|---|---|
| http://localhost:8080/xyz | ✅(通配符匹配) |
| http://localhost:8080/movie/abc | ✅(组件内 API 报错后跳转) |
| http://localhost:8080/movie/1234567(ID 不存在) | ✅(TMDB 返回 404 后跳转) |
| http://localhost:8080/actor/tt789(演员 ID 不存在) | ✅(同理在 ActorDetailsView 中处理) |
通过“路由约束 + 组件级服务端校验 + 全局守卫辅助”,即可构建健壮、语义清晰、用户体验一致的 404 处理体系——它不是兜底魔法,而是分层防御的工程实践。