Frameworks, Platforms and Libraries/Vue.js

Vue Class Component with Decorator

iam102 2023. 9. 16. 16:00

기존에 Vue 2 버전을 쓰는 경우 TypeScript의 도입이 매끄럽지 않지만 TypeScript와 같이 사용하기 위하여 Vue.extend()를 사용하여 객체로 만들어 사용하는 방법과 Class Component 형태로 만들어 쓰는 두 가지 방법 중 하나를 선택하여 사용합니다. 현재 운영 중인 Vue.js기반의 application의 경우는 이 중에서 Class Component로 만들어 사용하고 있으며 Decorator를 좀 더 활용하기 위해 추가로 라이브러리를 이용하여 구성했습니다. 그래서 어떻게 Decorator를 이용하여 Vue Class Component를  어떻게 구성했는지 소개하려고 합니다.

 

Vue Class Component Example

기본적인 Vue Class Component 형태는 vue-class-component를 이용하여 구성합니다.

// https://class-component.vuejs.org/
<template>
  <div>
    <button v-on:click="decrement">-</button>
    {{ count }}
    <button v-on:click="increment">+</button>
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'vue-class-component'

// Define the component in class-style
@Component
export default class Counter extends Vue {
  // Data
  count = 0

  // Methods
  increment() {
    this.count++
  }
  decrement() {
    this.count--
  }
  
  // Computed Properties
  get countPlusOne() {
    return this.count + 1;
  }
  
  // Vue lifecycle hooks
  mounted() {
    console.log('mounted');
  }
  destroyed() {
    console.log('destroyed');
  }
  
}
</script>

Vue Instance를 Vue Class Component 형태로 나타낸 예제입니다.

 

하지만 vue-property-decorator 라이브러리를 통해 좀 더 Decorator를 활용하려고 합니다. vue-property-decorator는 Vue에서 Class Component 형태로 개발을 도와주는 Decorator를 지원하는 라이브러리이며 vue-class-component 라이브러리를 완전히 의존하지만 Vue에서 정식으로 제공하는 라이브러리는 아닙니다.

 

vue-property-decorator example

자주 쓰는 Decorator 위주로 예시를 구성했습니다.

// Component.vue
<template>
  <!-- template -->
  <div ref="divEl">
    <AnotherComponent ref="anotherComponent" />
    <TestComponent />
  </div>
</template>

<script lang="ts">
import {
  Vue,
  Component,
  Prop,
  PropSync,
  Watch,
  Ref,
} from 'vue-property-decorator';
import TestComponent from '@/components/TestComponent.vue';
import AnotherComponent from '@/components/AnotherComponent.vue'

@Component({
  name: 'Component',
  components: {
    TestComponent,
  },
})
export default class extends Vue {
  @Prop() readonly num!: number;
  @PropSync('text', { type: String }) syncedText!: string;

  @Watch('flag', { immediate: true, deep: true })
  onFlagChanged(val: boolean, oldVal: boolean) {};

  @Ref() readonly divEl!: HTMLDivElement;
  @Ref() readonly anotherComponent!: AnotherComponent;
  
  private flag = false;
}
</script>

<style lang="scss" scoped>
  // style
</style>

@Component, mixins의 경우 vue-class-component에서 제공하는 Decorator를 그대로 사용하며 그 외 Decorator의 경우 vue-property-decorator에서만 사용 가능한 Decorator입니다.

 

Vue에서 사용하는 props, watch, ref, emit 등을 Decorator를 이용하여 사용할 수 있고 @PropsSync, @ModelSync 등 기존에 없던 옵션들도 Decorator를 이용하여 사용할 수 있습니다. Decorator의 종류는 vue-property-decorator의 github에서 볼 수 있습니다.

 

Vuex Class Example

Vue의 Store를 구성할 수 있는 Vuex도 Decorator를 이용하여 Class 형태로 만들 수 있습니다. vuex-module-decorators를 이용하여 구성할 수 있지만 vue-property-decorator와 마찬가지로 Vue에서 정식으로 제공하는 라이브러리는 아닙니다.

 

vuex-module-decorators example

Vuex를 구성하는 방법은 기존과 동일합니다.

// store/index.ts
import Vue from 'vue';
import Vuex from 'vuex';

import ApptModule, { AppState } from './modules/app';

Vue.use(Vuex);

export interface RootState {
  app: AppState;
}

export default new Vuex.Store<RootState>({
  modules: {
    app: AppModule,
  },
});

 

기본적으로 Vuex를 구성하는 State, Mutation, Action, Getters를 Decorator를 이용하여 Class 형태로 구성합니다.

// store/modules/app.ts
import { VuexModule, Module, Mutation, Action } from 'vuex-module-decorators';

export interface AppState {
  data: string;
}

@Module({ namespaced: true }) 
class App extends VuexModule implements AppState { 
  public data: string = 'snippet'; 
  
  @Mutation 
  private SET_DATA(data: string) {
    this.data = data; 
  } 
  
  @Action({ commit: 'SET_DATA', rawError: true })
  public setData(data: string) { 
    
  } 
  
  get appData(): string { 
    return this.data; 
  } 
}

export default App;

 

마무리

현재 Vue 3가 나왔지만 아직 Vue 2를 사용하고 있거나 레거시로 남아 있는 경우가 있습니다. Vue 2와 TypeScript를 같이 사용하기 위해 Class Component 형태로 개발을 진행한다면 vue-property-decorator와 vuex-module-decorators를 이용하여 좀 더 수월하게 개발할 수 있겠습니다.

 


참고 자료

https://class-component.vuejs.org/

https://github.com/kaorun343/vue-property-decorator

https://github.com/championswimmer/vuex-module-decorators