Vue Router 4布局无法渲染子组件问题求助
解决Vue Router 4中Home.vue无法在Main.vue内渲染的问题
问题现象
- 访问
/路径时,仅渲染Main.vue,Home.vue无法在其内部显示 - 访问
/login路径时,FullPage.vue可正常渲染Login.vue - 访问不存在的路由时,FullPage.vue可正常渲染404.vue
相关代码
App.vue
<template> <router-view></router-view> </template> <script> export default { name: 'App' } </script>
Main.vue
<template> <div> main <div id="content"> <div class="content-wrapper"> <div class="content-area"> <router-view></router-view> </div> </div> </div> </div> </template>
Home.vue
<template> <div> Home </div> </template>
FullPage.vue & Login.vue
<!-- FullPage.vue --> <template> <div class="full-page"> full page <router-view></router-view> </div> </template> <!-- Login.vue --> <template> <div> login form </div> </template>
router.js
import { createRouter, createWebHistory } from 'vue-router' import { store } from './store/store' const router = new createRouter({ history: createWebHistory('/'), routes: [ { // MAIN LAYOUT ROUTES path: '', component: () => import('@/src/layouts/main/Main.vue'), meta: { requiresAuth: true }, children: [ { path: '/', name: 'home', component: () => import('@/src/views/Home.vue'), } ], }, // FULL PAGE LAYOUT { path: '', component: () => import('@/src/layouts/full-page/FullPage.vue'), children: [ { path: 'login', name: 'login', component: () => import('@/src/views/pages/Login.vue') }, { path: 'error-404', name: 'error-404', component: () => import('@/src/views/pages/404.vue') }, { path: 'error-403', name: 'error-403', component: () => import('@/src/views/pages/403.vue') }, ] }, // if no match found, redirect to /error-404 { path: '/:pathMatch(.*)*', name: 'not-found', redirect: '/error-404' } ], }) router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { if (store.getters.isAuthenticated) { next() } else { next({ name: 'login' }) } } else { next() } }) export default router
问题原因
- 两个顶级路由的
path都设置为'',Vue Router匹配时会优先命中第一个,但子路由使用绝对路径/会打破父子路由的嵌套关系——子路由的绝对路径会被视为独立路由,而非父路由的子路由,导致Home.vue无法加载到Main.vue的<router-view>中。 - 当把子路由
path改为/home时,路径结构符合父子路由的匹配逻辑,所以问题解决,但这不是最优的默认首页配置方式。
解决方案
调整路由配置,让Main.vue作为/路径的父路由,子路由设为默认子路由(空字符串''),同时给FullPage.vue的顶级路由设置明确前缀,避免匹配冲突:
修改后的router.js:
import { createRouter, createWebHistory } from 'vue-router' import { store } from './store/store' const router = createRouter({ history: createWebHistory('/'), routes: [ { // MAIN LAYOUT ROUTES path: '/', component: () => import('@/src/layouts/main/Main.vue'), meta: { requiresAuth: true }, children: [ { path: '', // 作为父路由的默认子路由 name: 'home', component: () => import('@/src/views/Home.vue'), } ], }, // FULL PAGE LAYOUT { path: '/pages', // 给FullPage路由设置前缀 component: () => import('@/src/layouts/full-page/FullPage.vue'), children: [ { path: 'login', name: 'login', component: () => import('@/src/views/pages/Login.vue') }, { path: 'error-404', name: 'error-404', component: () => import('@/src/views/pages/404.vue') }, { path: 'error-403', name: 'error-403', component: () => import('@/src/views/pages/403.vue') }, ] }, // 未匹配路由重定向 { path: '/:pathMatch(.*)*', name: 'not-found', redirect: '/pages/error-404' } ], }) router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { store.getters.isAuthenticated ? next() : next({ name: 'login' }) } else { next() } }) export default router
如果不想给FullPage路由加前缀,也可以调整路由顺序,把FullPage路由放在Main路由之后,但更推荐给不同布局的路由设置明确前缀,避免匹配歧义。
内容的提问来源于stack exchange,提问作者kopz
相关产品推荐
相关产品推荐

