티스토리 뷰

안녕하세요. 

이번에는 여러개의 vue component를 팝업으로 띄울때 dynamic component를 이용하는 법에 대해 적어보겠습니다.

 

일단 아래 예제를 살펴보겠습니다.

<template>
  <v-btn @click="open(A)">Open A</btn>
  <v-btn @click="open(B)">Open B</btn>
  <v-dialog v-model="dialogA.isOpen">
    <custom-component-a :arg="arg" />
  </v-dialog>
  <v-dialog v-model="dialogB.isOpen">
    <custom-component-b :arg="arg" />
  </v-dialog>
</template>

<script>
import CustomComponentA from './CustomComponentA.vue'
import CustomComponentB from './CustomComponentB.vue'

export default {
  components: {
    CustomComponentA,
    CustomComponentB
  },
  data () {
   return {
     arg: null,
     dialogA: false,
     dialogB: false
   }
  },
  methods: {
   open (param) {
     this.arg = param
     this[`dialog${param}`] = true
   }
  }
}
</script>

 위 예제는 두개의 버튼이 있고 'Open A' 를 클릭하면 A 가 팝업되고, 'Open B'를 클릭하면 B 가 팝업되는 단순한 구조입니다.

 

 위 예제는 짧게 작성되어 있지만, 화면이 좀 더 복잡해 지기 시작하면 코드는 한 줄이라도 줄이는게 보기도 좋고 유지보수에도 도움이 됩니다. 그리고 사용할지 말지도 모르는 popup 컴퍼넌트를 미리 import / rendering 해 놓는것도 좀 부담이 됩니다.

 

이때 vue에서는 매우 재미있는 기능 하나를 제공합니다. 바로 다이나믹 컴퍼넌트 라는 방식이며 기본 설명은 공식 문서에 아주 잘 되어 있습니다.

kr.vuejs.org/v2/guide/components-dynamic-async.html

 

동적 & 비동기 컴포넌트 — Vue.js

Vue.js - 프로그레시브 자바스크립트 프레임워크

kr.vuejs.org

그럼 이제 다이나믹 컴퍼넌트를 사용하여 위 예제를 재 작성 해 보겠습니다.

<template>
  <v-btn @click="open(A)">Open A</btn>
  <v-btn @click="open(B)">Open B</btn>
  <v-dialog v-model="dialog.isOpen">
    <component v-if="customComponent" :is="customComponent" :arg="arg" />
  </v-dialog>
</template>

<script>
import CustomComponentA from './CustomComponentA.vue'
import CustomComponentB from './CustomComponentB.vue'
export default {
  data () {
   return {
     arg: null,
     dialog: false,
     customComponent: null
   }
  },
  methods: {
   open (param) {
     this.arg = param
     this.customComponent = param === 'A' ? CustomComponentA : CustomCompoentB
     this.dialog = true
   }
  }
}
</script>

위의 '<component :is=>' 를 사용함으로써 동적으로 컴포넌트를 랜더링 할 수 있게 되었습니만, 이 경우라도 import 는 미리 되어 있는 상태이므로 import 를 비동기적으로 다시 변경하겠습니다.

<template>
  <v-btn @click="open(A)">Open A</btn>
  <v-btn @click="open(B)">Open B</btn>
  <v-dialog v-model="dialog.isOpen">
    <component v-if="customComponent" :is="customComponent" :arg="arg" />
  </v-dialog>
</template>

<script>
export default {
  data () {
   return {
     arg: null,
     dialog: false,
     customComponent: null
   }
  },
  methods: {
   open (param) {
     this.arg = param
     this.customComponent = async () => (await import(`./CustomComponent${param}.vue`)).default
     this.dialog = true
   }
  }
}
</script>

위와 같이 구현하여 사용하지 않는 component에 대한 import / rendering 을 줄이고 소스도 좀 더 단순화 할 수 있게 되었습니다.

 

* 추가로 한번 랜더링된 컴포넌트를 계속 유지하고 싶은 경우 <keep-alive> 엘리먼트로 둘러 싸서 해결합니다. 

 

감사합니다.

댓글