Vue3:通过name属性编程式跳转路由触发错误问题排查
Let's break down what's happening here and how to fix it.
The core issue you're facing is that when you call router.push inside onBeforeMount, the component's rendering process has already started. Even though you trigger a redirect to the 404 page, the AirportDetail template still tries to render first—and since airport.value is undefined for invalid codes, accessing properties like airport.name in your template throws the Cannot read properties of undefined error you're seeing.
Other 404 scenarios work because they're caught directly by your /:catchAll(.*)* route rule, which loads the 404 component without ever touching AirportDetail. But in this case, the URL matches the /airports/:code route, so AirportDetail gets loaded first, and the redirect happens too late to prevent the failed render.
Fixes to Try
1. Add Null Safety in the Template (Quick Fix)
Wrap your template content in a v-if check to ensure you only render when airport exists. This prevents the template from trying to access properties on an undefined value:
<template> <div v-if="airport"> <h1>{{ airport.name }}</h1> <!-- Rest of your component content --> </div> </template>
You can also use optional chaining (airport?.name) for individual properties if you prefer, but the v-if approach hides the entire component until the data is valid.
2. Validate Before Component Load (Recommended)
Move the airport check to a route guard so you block access to AirportDetail entirely if the code is invalid. This is cleaner because it handles the check at the routing level, before the component even loads.
Modify your route configuration like this:
// Import or define your airports data here const airports = [/* Your airport array */] const routes = [ // ... other routes { path: '/airports/:code', name: "AirportDetail", component: () => import('@/pages/AirportDetail.vue'), // Add this beforeEnter guard beforeEnter: (to, from, next) => { const airportCode = to.params.code.toUpperCase() const isValidAirport = airports.some(airport => airport.abbreviation === airportCode) if (isValidAirport) { next() // Proceed to the component } else { next({ name: 'PageNotFound' }) // Redirect to 404 } }, children: [ { path: 'destinations', name: 'AirportDestinations', component: () => import('@/pages/AirportDestinations.vue') } ] }, { path: '/:catchAll(.*)*', name: 'PageNotFound', component: () => import('@/pages/PageNotFound.vue') } ]
This way, invalid airport codes are caught before AirportDetail is ever initialized, eliminating the render error entirely.
3. Capture the Error (Last Resort)
If you need to keep the check inside the component, use Vue's onErrorCaptured hook to catch the render error:
import { onErrorCaptured } from 'vue' // Inside your component setup onErrorCaptured((err) => { // Check if this is the error we're expecting if (err.message.includes('Cannot read properties of undefined')) { return false // Allow the error to propagate (but the redirect should already handle it) } })
This is less ideal than the first two fixes, but it can suppress the error messages if needed.
Final Recommendation
Go with the route guard approach (option 2). It aligns with Vue Router's intended pattern for handling route validation, keeps your component logic cleaner, and avoids unnecessary component loading/rendering for invalid routes.
内容的提问来源于stack exchange,提问作者Robert Wildling

