본문 바로가기

Vue.js

[Vue js] dynamic component, 원하는 컴포넌트 호출하기 + defineAsyncComponent()

개요

 

하나의 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>