ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 5. 컴퍼넌트와 데이터 전달 (component, props, $emit)
    Vue For Beginner 2019. 10. 1. 22:19

    vue의 컴퍼넌트는 view를 이루는 작은 단위로 라이프사이클과 상태를 가지고 있습니다. 이러한 컴퍼넌트를 조합하여 하나의 화면이 완성이 되는 것 입니다. 그리고 컴퍼넌트를 어떻게 나누는가는 프로젝트와 개발자의 성향에 따라 달라지게 되는데 여기서는 아주 일반적인 케이스로 본인의 스타일에 따라 응용이 가능하도록 설명하겠습니다. 

     

    1. 컴퍼넌트의 생성

    컴퍼넌트는 아래와 같은 형태로 생성할 수 있습니다. 

    Vue.component('my-component', {
      template: '<button>버튼!</button>',
      data: function () {
        return data
      }
    })

    하나의 버튼을 하나의 컴퍼넌트로 생성하였고 이 컴퍼넌트는 `<my-component></my-component>`와 같은 형태로 다양한 영역에서 사용할 수 있습니다. vue-cli를 활용하면 .vue파일이 컴퍼넌트가 되고 기본조건으로 생성한다면 app.vue와 helloWorld.vue 두개의 컴퍼넌트가 생성되고 class문법으로 작성되어 있습니다.

    <template>
      <div id="app">
        <img width="25%" src="./assets/logo.png">
        <HelloWorld msg="Hello Vue in CodeSandbox!" />
      </div>
    </template>
    
    <script>
    import HelloWorld from "./components/HelloWorld";
    
    export default {
      name: "App",
      components: {
        HelloWorld
      }
    };
    </script>
    
    <style>
    #app {
      font-family: "Avenir", Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    

     

    대부분의 경우 후자의 형태를 사용하므로 두번째 형태를 기준으로 설명이 이루어집니다.

     

    2. 컴퍼넌트의 종류

    위의 케이스에서 볼 수 있듯이 하나의 버튼이 하나의 컴퍼넌트일 수 있고, 한 화면전체를 하나의 컴퍼넌트로 구성할 수 있습니다.

     

    위의 두번째 케이스의 코드를 보면 App컴퍼넌트가 HelloWorld컴퍼넌트를 사용하고 있습니다. 이는 결국엔 부모-자식관계로 이루어지고 컴퍼넌트 입장에서 보면 사용이 되어지는 컴퍼넌트와 사용하는 컴퍼넌트로 구분된다고 볼 수 있습니다.

     

    다시말하면 사용이 되어지는 자식컴퍼넌트는 위로부터 데이터를 받게 됩니다. 이는 컴퍼넌트간의 데이터 전달이 이루어 진다는 점을 생각해 볼 수 있으며 사용되어지는 자식컴퍼넌트는 함수와 같이 부모로부터 받은 데이터에 따라 다른 데이터를 보여주거나 형태를 달리할 수 있습니다. 반대로 자식컴퍼넌트에서 발생된 이벤트는 부모에게 알려서 데이터를 갱신하게 됩니다.

     

    3. props (부모 => 자식으로 데이터를 전달)

    간단하게 부모가 가진 데이터를 자식으로 전달하여 리스트를 생성하는 기능을 만들어보면 다음과 같습니다.

     

    app.vue

    <template>
      <div id="app">
        <Card v-for="v in myList" :key="v" :cardNumber="v"/>
      </div>
    </template>
    
    <script>
    import Card from "./components/Card";
    
    export default {
      name: "App",
      components: {
        Card
      },
      data() {
        return {
          myList: ["1", "2"]
        };
      }
    };
    </script>
    

    components/Card.vue

    <template>
      <div class="card">{{cardNumber}}</div>
    </template>
    
    <script>
    export default {
      name: "Card",
      props: {
        cardNumber: String
      }
    };
    </script>
    
    <style>
    .card {
      display: inline-block;
      height: 50px;
      width: 50px;
      margin: 10px;
      background: red;
    }
    </style>
    

     

    여기까지 매우 간단한 컴퍼넌트를 구성하여 props사용법을 경험하였습니다. app의 myList데이터를 가지고 카드를 생성하였습니다. 간단히 설명하면 부모컴퍼넌트는 :cardNumber 으로 데이터를 바인딩하여 내려주고 자식컴퍼넌트는 porps를 통해 받게 된 것입니다. Card컴퍼넌트는 각각 디자인과 기능을 포함할 수 있으므로 다양하게 재사용 될 수 있습니다.

    4. $emit (자식이 부모에게 알리기)

    자식컴퍼넌트는 일반적으로 데이터를 부모로부터 받게 됩니다. 그런데 자식컴퍼넌트에서 일어난 이벤트에 따라 부모컴퍼넌트에 데이터가 변경되어야 한다면 어떻게 할까요? 이때 사용되는 것이 $emit입니다. 위에 기능에 카드를 추가하는 기능을 가진 컴퍼넌트를 추가해보겠습니다. 

     

    components/AddItem.vue

    <template>
      <div>
        <input type="text" v-model="inputData">
        <button @click="addItem()">추가하기</button>
      </div>
    </template>
    
    <script>
    export default {
      name: "AddItem",
      data() {
        return {
          inputData: null
        };
      },
      methods: {
        addItem() {
          if (!this.inputData) {
            return false;
          }
          this.$emit("addItem", this.inputData);
        }
      }
    };
    </script>

    input과 버튼으로 이루어진 간단한 UI입니다. 버튼이 클릭될때 해당컴퍼넌트는 부모로 데이터를 전달하게 됩니다. 그럼 부모컴퍼넌트는 이벤트를 전달받아 데이터를 수정한다면  카드를 추가할 수 있는 기능을 완성시킬 수 있습니다.

     

    app.vue

    <template>
      <div id="app">
        <Card v-for="v in myList" :key="v" :cardNumber="v"/>
        <add-item v-on:addItem="addItem"/>
      </div>
    </template>
    
    <script>
    import Card from "./components/Card";
    import AddItem from "./components/AddItem";
    
    export default {
      name: "App",
      components: {
        Card,
        AddItem
      },
      data() {
        return {
          myList: ["1", "2"]
        };
      },
      methods: {
        addItem(v) {
          this.myList.push(v);
        }
      }
    };
    </script>
    

    v-on:[자식컴퍼넌트 이벤트 이름]="실행할 함수" 의 형태로 이벤트를 수신받고 매서드를 실행할 수 있습니다. 여기서 addItem매서드는 데이터를 추가하고 데이터가 추가되면 카드가 추가로 생성되는 구조입니다.

     

    아주 간단한 UI를 만들어보며 컴퍼넌트와 데이터가 전달되는 과정을 알아보았습니다. 디테일한 문법보다는 전체적인 그림이 그려지도록 설명하였고 이를 바탕으로 한번 혼자 만들어본다면 vue의 기본적인 과정을 이해했다고 볼 수 있습니다. 이를 바탕으로 응용하는 부분은 직접 무언가를 만들고  막히는 부분을 찾아보면서 해결해보는 과정이 필요합니다.

     

    다음으로 slot, filter, eventbus, vuex, router 등 다양한 개념들과 기능이 나오지만 이는 지금까지의 내용을 도와주는 기능으로  현재까지 내용이 숙달되었다면 앞으로 더 쉽게 배워갈 수 있습니다.

     

     

    댓글

Designed by Tistory.