Dialog 분리하기

Table of Content

목적

Vuetify 에서 제공하는 예제코드를 살펴보자. link

- main-component
  └ index.vue
<template>
  <v-container>
    <!-- Main Content -->
    <!-- Dialog Btn -->
    <v-btn @click="dialogFlag = !dialogFlag">Show Dialog</v-btn>
    <v-dialog v-model="dialogFlag" width="500">
      <v-card>
        <v-card-title class="headline grey lighten-2" primary-title>
          Sandbox Dialog
        </v-card-title>
        <v-btn color="primary" flat @click="onAcceptBtn">
          I accept
        </v-btn>
      </v-card>
    </v-dialog>
  </v-container>
</template>

<script>
  export default {
    data: function() {
      return {
        dialogFlag: false
      };
    },
    methods: {
      onAcceptBtn: function() {
        this.dialogFlag = false;
        this.doAfterAccept();
      },
      doAfterAccept: function() {
        console.log("I did after accept");
      }
    }
  };
</script>

이대로 사용하여도 기능은 문제가 없이 동작한다. 하지만 다이얼로그 하나를 추가하기 위해서 코드는 약 20줄 가량 늘어났다. 여기서 할일은 다이얼로그 컴포넌트를 분리하고 다이얼로그에서 accept 버튼을 눌렀을때 우리가 원하는 로직이 실행되게 하는 것이다. 이렇게 작성하면 코드의 길이를 15줄 정도 줄일 수 있고, 다이얼로그를 많이 사용할 수록 그 효과는 더욱 크다.


다이얼로그가 보여지고 감춰주는 로직은 메인 컴포넌트에서 관심있어하는 부분이 아니다. 마찬가지로 다이얼로그에 표시되는 라벨이나 타이틀도 메인컴포넌트에서 관심있어하는 부분은 아니다. 메인컴포넌트에서는 두가지만 관심이 있는 것이다. 클릭을 했을 때 다이얼로그가 보여지는 것과 accept를 눌렀을 때 어떤 로직(이하 acceptCallback)이 실행 될지.


코드를 분리하기 위해서 다이얼로그와 관련된 코드를 local component로 이동한다. (local component를 등록하는 방법)클릭을 했을 때 다이얼로그가 보여지게 하기 위해서는 local componentrefs로 등록하고 local componentflag에 직접 접근하여 값을 변경한다. accept callback을 전달하기 위해서는 local component에서 props:Function으로 main component의 함수를 전달한다.


목적을 달성한 코드는 아래와 같다.

\- main-component
 | \- dialog-factory
 |  └ my-first-dialog.vue
 └ index.vue
<template>
  <v-container>
    <!-- Main Content -->
    <!-- Dialog Btn -->
    <v-btn @click="$refs.myFirstDialog.dialogFlag = true">Show Dialog</v-btn>
    <!-- Dialog -->
    <my-first-dialog
      ref="myFirstDialog"
      :acceptCallback="doAfterAccept"
    ></my-first-dialog>
  </v-container>
</template>

<script>
  import MyFirstDialog from "./dialog-factory/my-first-dialog";

  export default {
    components: {
      MyFirstDialog
    },
    methods: {
      doAfterAccept: function() {
        console.log("I did after accept");
      }
    }
  };
</script>
<template>
  <v-dialog v-model="dialogFlag" width="500">
    <v-card>
      <v-card-title class="headline grey lighten-2" primary-title>
        Sandbox Dialog
      </v-card-title>
      <v-btn color="primary" flat @click="onAcceptBtn">
        I accept
      </v-btn>
    </v-card>
  </v-dialog>
</template>

<script>
  export default {
    props: {
      acceptCallback: Function
    },
    data: function() {
      return {
        dialogFlag: false
      };
    },
    methods: {
      onAcceptBtn: function() {
        this.dialogFlag = false;
        this.acceptCallback();
      }
    }
  };
</script>