본문 바로가기
Study/Vue

Vuejs ) TodoApp (Vue2에서 Vue3으로)

by JongIk 2022. 3. 20.
반응형

TypeScript 를 적용해 Vue2, Vue3 만든 TodoApp 비교

Inflearn 강좌 "Vue.js+TypeScript 완벽가이드" (장기효) 를 참고하며 제작한 Vue2 버전의 TodoApp 을 Vue3 Options API 기반으로 다시 제작해보았습니다.

아래 링크를 통해 Github 로 접속한 뒤 README 파일의 브랜치 설명을 참고하셔서 Vue3 버전의 전체 코드를 확인하실 수 있습니다.

Github 에서 확인하기

실행화면


코드 비교

TypeScript 사용

두 개의 프로젝트 모두 vue-cli 로 프로젝트를 생성하는 시점에 TypeScript를 적용해 생성했습니다.

Vue 2 버전에서는
<script lang="ts">
와 같이 script 태그를 설정한 뒤 바로 TypeScript 를 적용해볼 수 있었습니다.

하지만 Vue3 버전의 경우 TypeScript 에서 Vue Component 내의 타입을 올바르게 추론하려면

<script lang="ts">
  import { defineComponent } from "vue";
  export default defineComponent({
      // 생략
  })
</script>

의 형태로 script 코드를 작성해야합니다.

defineComponent 는 전달된 객체를 반환하는 것 이외에는 아무것도 하지 않지만, 입력에 관해서는, 반환된 값에는 수동 렌더링 함수, TSX 및 IDE 도구의 지원을 위한 생성자의 합성 유형이 있습니다.


v-model vs Input 이벤트

Vue 2

  • App.vue (상위)
<!-- template -->
<TodoInput
        :item="todoText"
        @input="updateTodoText"
        @add="addTodoItem"
></TodoInput>
<!-- script -->
<script lang="ts">
  // emit으로 받은 입력값을 data의 todoText에 저장
  updateTodoText(value: string) {
    this.todoText = value;
  },

  // emit 으로 받은 이벤트가 동작하는 부분
  addTodoItem() {
      // 생략 
  },              
</script>
  • TodoInput.vue (하위)
<!-- template -->
<input
      type="text"
      :value="item"
      @input="handleInput"
      @keyup.13="addTodo"
/>
    <button class="btn" @click="addTodo" type="button">추가</button>

<!-- script -->
<script lang="ts">
  // props 에 대한 type 유효성 검사
  props: {
    item: {
      type: String,
      required: true,
    },
  },
  methods: {
    handleInput(event: InputEvent) {
      const eventTarget = event.target as HTMLInputElement;
      this.$emit("input", eventTarget.value);
    },
    addTodo() {
      this.$emit("add");
    },
  },
</script>
  • IME (중국어, 일본어, 한국어 등)가 필요한 언어 (Vue2) 의 경우 IME 중 v-model이 업데이트 되지 않습니다. 그렇기 때문에 Input 이벤트를 사용했습니다.
  • v-model 과 input 이벤트 비교

Vue 3

하지만 Vue3 버전부터 위에서 말한 IME이슈 (한글을 입력할 때 한 글자씩 늦게 binding 됨) 가 해결되었기 때문에 v-model 을 사용해도 무방합니다.

  • App.vue (상위)
<!-- template -->
<TodoInput v-model="todoText" @add="addTodoItem"></TodoInput>
<!-- script -->
<script lang="ts">
  data() {
    return {
      todoText: "" as string,
    };
  },
  methods:{
      addTodoItem(){
        // 생략
      }
  }
</script>
  • TodoInput.vue (하위)
<!-- template -->
<input
      :value="modelValue"
      type="text"
      @input="onInput"
      @keyup.enter="addTodo"
/>
<button class="btn" @click="addTodo" type="button">추가</button>
<!-- script -->
<script lang="ts">
props: ["modelValue"],
methods: {
    // TodoInput 컴포넌트에서 입력하지만 입력한 데이터는 App.vue 에서 관리된다.
    onInput(event: InputEvent) {
      const eventTarget = event.target as HTMLInputElement;
      this.$emit("update:modelValue", eventTarget.value);
    },
}
</script>

Vue3 ) Options API 와 Composition API 의 비교

Vue3 의 Composition API 를 학습하면서
위 TodoApp을 제작한 뒤 다시 Vue3 Composition API 를 기반으로 TodoApp을 제작해봤습니다.

아래 글에서 OptionsAPI 와 Composition API 를 비교하는 글을 볼 수 있습니다.

 

Vue3 ) TodoApp 을 통한 OptionsAPI 와 Composition API 비교

Vue3 ) TodoApp 을 통한 OptionsAPI 와 Composition API 비교 같은 동작을 하는 TodoApp 을 각각 OptionsAPI 와 Composition API 를 이용해 제작했습니다. 전체 코드는 아래 링크를 통해 Github 에서 확인하실 수..

jongik.tistory.com

 

반응형

댓글