You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3应用中带参数的路由为何无法显示404视图?

Vue 3 + TypeScript 动态路由无效参数不触发404的问题与修复

问题描述

我正在用Vue 3、TypeScript和TMDB API开发SPA,配置404页面后,访问根URL下的随机路径(如http://localhost:8080/someNonExistingPath)能正常显示404,但访问动态路由的无效参数(如http://localhost:8080/movie/a615656)时,却不会触发404视图。

当前路由配置src/router/index.ts:

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import HomeView from '../views/HomeView.vue';
import TopRatedMoviesView from '../views/TopRatedMoviesView.vue';
import MovieDetailsView from '../views/MovieDetailsView.vue';
import ActorDetailsView from '../views/ActorDetailsView.vue';
import NotFoundView from '../views/NotFoundView.vue';

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/top-rated',
    name: 'top_rated',
    component: TopRatedMoviesView
  },
  {
    path: '/movie/:id',
    name: 'movie_details',
    component: MovieDetailsView
  },
  {
    path: '/actor/:id',
    name: 'actor_details',
    component: ActorDetailsView
  },
  {
    path: '/:pathMatch(.*)*',
    name: "404",
    component: NotFoundView
  },
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

404视图src/views/NotFoundView.vue代码:

<template>
  <div class="container d-flex">
   <div class="text-center">
      <h1 class="mb-3">404 | page not found</h1>
      <router-link class="btn btn-sm btn-success" to="/">
        <strong>Go to the Homepege</strong>
      </router-link>
   </div>
  </div>
</template>

<script lang="ts">
  import { defineComponent } from 'vue';

  export default defineComponent({
    name: 'NotFoundView',

  });
</script>

原因分析

路由匹配按配置顺序执行:当访问/movie/a615656时,路由系统会优先匹配/movie/:id规则(:id可匹配任意字符串),加载MovieDetailsView组件,不会走到最后的404路由。只有当路径完全不匹配前面所有规则时,才会触发/:pathMatch(.*)*的404路由。

可靠修复方案

方案1:动态路由组件内校验数据,不存在则跳转404

在MovieDetailsView和ActorDetailsView中,调用TMDB API获取数据后判断是否存在,若返回空或请求失败,通过router.push跳转到404页面。

以MovieDetailsView为例:

<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
// 假设你有封装的TMDB API请求函数
import { getMovieDetails } from '@/api/tmdb';

export default defineComponent({
  name: 'MovieDetailsView',
  setup() {
    const route = useRoute();
    const router = useRouter();

    onMounted(async () => {
      try {
        const movie = await getMovieDetails(route.params.id as string);
        // 数据为空则跳转404
        if (!movie) {
          router.push({ name: '404' });
          return;
        }
        // 正常处理电影数据
      } catch (error) {
        // 捕获请求错误,跳转404
        router.push({ name: '404' });
      }
    });

    return {};
  },
});
</script>

方案2:使用路由守卫(beforeEnter)提前校验

在动态路由配置中添加beforeEnter守卫,提前请求API校验参数有效性,无效则跳转到404。

修改路由配置:

// 导入API函数
import { getMovieDetails, getActorDetails } from '@/api/tmdb';

const routes: Array<RouteRecordRaw> = [
  // ...其他路由
  {
    path: '/movie/:id',
    name: 'movie_details',
    component: MovieDetailsView,
    beforeEnter: async (to) => {
      try {
        const movie = await getMovieDetails(to.params.id as string);
        if (!movie) return { name: '404' };
      } catch (error) {
        return { name: '404' };
      }
    }
  },
  {
    path: '/actor/:id',
    name: 'actor_details',
    component: ActorDetailsView,
    beforeEnter: async (to) => {
      try {
        const actor = await getActorDetails(to.params.id as string);
        if (!actor) return { name: '404' };
      } catch (error) {
        return { name: '404' };
      }
    }
  },
  // ...404路由
]

方案3:限制动态参数格式(辅助优化)

如果TMDB的id是纯数字,可以在路由路径中用正则限制id仅匹配数字,非数字参数会直接走到404路由。注意:该方案仅过滤格式错误的id,无法处理格式正确但不存在的id,需配合前两种方案使用。

修改路由路径:

{
  path: '/movie/:id(\\d+)', // 仅匹配数字id
  name: 'movie_details',
  component: MovieDetailsView
},
{
  path: '/actor/:id(\\d+)',
  name: 'actor_details',
  component: ActorDetailsView
},

总结

最可靠的方案是方案1或方案2,能真正校验参数对应的资源是否存在;方案3作为辅助手段,可减少无效API调用。

内容的提问来源于stack exchange,提问作者Razvan Zamfir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:42:42