vue router 를 중첩 라우팅 처리하면서 발생한 이슈입니다.
컴포넌트에 전달된 속성(attribute)가 렌더링 과정에서 적절히 처리되지 못했을 경우에 발생합니다.
experienceSlug 라는 속성을 컴포너트에 전달했지만, 해당 속성이 컴포넌트 내부에서 명시적으로 처리되지 않았거나, 컴포넌트가 Fragment 또는 텍스트 노드만 반환하는 경우 발생합니다.
Vue 3에서 기본적으로 props가 아닌 속성(non-props attributes)은 루트 엘리먼트로 자동으로 전달됩니다. 하지만 컴포넌트가 Fragment나 텍스트 노드를 반환할 경우 속성을 전달할 루트 엘리먼트가 없어 이 경고가 발생합니다.
router-view 는 상위 app.vue에 존재합니다.
{
name: 'destination',
path: '/destination/:slug',
props: true,
component: () => import ('@views/destination.vue')
},
{
name: 'experience',
path: '/destination/:slug/:experienceSlug',
props: route => ({...route.params, id: Number(route.params.id)}),
component: () => import ('@/views/experience.vue')
}
위의 코드를 아래와 같이 중첩 라우트로 변경되었습니다.
// router/index.ts
{
name: 'destination',
path: '/destination/:slug',
props: true,
component: () => import ('@views/destination.vue'),
children: [
{
name: 'experience',
path: ':experienceSlug',
props: route => ({...route.params, id: Number(route.params.id)}),
component: () => import ('@/views/experience.vue')
}
]
}
<!-- destination.vue -->
<section class="experiences">
<h2>Top Experience of {{ data.name }}</h2>
<div class="cards">
<RouterLink v-for="experience in data.experiences"
:key="experience.id"
:to="{name: 'experience', params: {experienceSlug: experience.slug}}"
>
<ExperienceCard :experience="experience"/>
</RouterLink>
</div>
<RouterView />
</section>
이 경우 중첩된 라우트의 이동을 시도하면 아래와 같이 콘솔창에 오류가 발생합니다.
Extraneous non-rops attributes (experienceSlug) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.
해결
컴포넌트에 experienceSlug 를 명시적으로 선언하면 해결할수 있다고 하지만 어느 컴포넌트에 선언해야하는지 조금 헷갈렸던것 같습니다.
routes/index 를 보면 destination 컴포넌트 내부에 experience 컴포넌트를 라우팅하는 구조입니다.
experienceSlug 를 가지고 중첩된 컴포넌트로 전달해주는 Destination 컴포넌트임으로 Destination 컴포넌트에 experienceSlug 속성을 선언해주어야합니다.
본문에 언급한 vue3 에서 props 가 아닌 속성은 기본적으로 root 엘리먼트로 전달되는 내용과 부합합니다.
// destination.vue
const props = defineProps({
slug: String,
experienceSlug: String
})
위 형태로 정의하면 콘솔상에서의 오류는 발생하지 않습니다.