개요
하나의 route 를 가지고 동적으로 컴포넌트 변경하기
Component 태그와 computed 활용
1. route 등록
동적 라우트 매칭을 통해 하나의 컴포넌트에 동적인 path를 받을 수 있도록 설정해 줍니다.
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
redirect: '/main'
},
{
path: '/main',
name: 'main',
component: () => import('../components/DefaultView.vue'),
children: [
{
path: '/main/:param1/:param2', // 동적 라우트 매칭
name: 'content',
component: () => import('../view/ContentView.vue')
}
]
}
]
})
2. component 태그
다음으로 route 에 지정한 component 에 아래와 같이 component 태그를 만들어 줍니다.
// ContentView.vue
<template>
<div>
<component :is="componentLoader" />
</div>
</template>
3. vue 등록 및 동적 매칭
computed 를 이용하여 route 의 param 값이 변경될 때마다 함수를 실행 하도록 구성하고,
path에 따라 다른 컴포넌트를 return 해줍니다.
// ContentView.vue
<script>
import FirstView from './components/dynamic-component/FirstView.vue';
import SecondView from './components/dynamic-component/SecondView.vue';
import ThirdView from './components/dynamic-component/ThirdView.vue';
import NotPage from './components/dynamic-component/NotPage.vue'
export default {
computed: {
componentLoader(){
const path = this.$route.params.param;
if(path == 'first'){
return FirstView;
}else if (path == 'second'){
return SecondView;
}else if (path == "third"){
return ThirdView;
} else {
return NotPage;
}
}
}
}
</script>
결과
아래와 같이 경로에 따라 다른 컴포넌트를 호출하는 것을 보실 수 있습니다.
문제점
위와 같이 컴포넌트를 동적으로 구성하게 되면 규모가 작은 프로젝트는 상관없지만, 규모가 커질수록 호출하는 컴포넌트가 많아져서 초기 실행속도에 지장을 줄 수 있습니다.
그래서 router 의 Lazy Loading 과 같이 코드를 구성해 보았습니다.
export default {
components: {
FristView: () => import('../components/dynamic-component/FirstView.vue')
},
computed: {
componentLoader(){
const path = this.$route.params.param;
if(path == 'first'){
return this.$options.components.FristView;
} else {
return NotPage;
}
}
}
}
결과는 undefiend erorr 입니다.
* 이 부분은 computed 와 vue 사이의 관계를 좀더 알아봐야할 거 같습니다.
해당 문제는 vue 에서 제공하는 defineAsyncComponent() 함수로 해결할 수 있습니다.
defineAsyncComponent()
<script>
import { defineAsyncComponent } from 'vue';
import NotPage from '../components/dynamic-component/NotPage.vue'
export default {
components: {
FristView: defineAsyncComponent( () => import('../components/dynamic-component/FirstView.vue'))
},
computed: {
componentLoader(){
const path = this.$route.params.param;
if(path == 'first'){
return this.$options.components.FristView;
}else {
return NotPage;
}
}
}
}
</script>
'Vue.js' 카테고리의 다른 글
Vue 3 bootstrap 적용하기 (0) | 2023.11.28 |
---|---|
[Vue] 네비게이션 가드 / Navigation Guards (0) | 2023.07.05 |
[Vue js] Vue Router / 뷰 라우터 (0) | 2023.05.07 |
[Vue js] i18n 을 이용하여 다국어 설정 (0) | 2023.05.05 |
[Vue js] Vue emit 부모 컴포넌트로 데이터 보내기 (0) | 2023.04.12 |