본문 바로가기
FrontEnd/Vue 2

[Vue.js] 컴포넌트간 통신, Props, Event Emit

by Chaedie 2022. 9. 15.
728x90

Vue에서의 컴포넌트간 통신 흐름

  • 상위 컴포넌트 => 하위 컴포넌트로 Props가 내려간다. (데이터가 내려간다.)
  • 하위 컴포넌트 => 상위 컴포넌트로 Event가 올라간다.

Vue에서의 Props

  • 개념은 react의 Props와 같다. 상위 컴포넌트에서 하위 컴포넌트로 전달해주는 데이터!
  • 데이터 흐름 또한 상위 컴포넌트 => 하위 컴포넌트로 같다.
  • props를 던져주는 방법은 v-bind:프롭스 속성 이름 ="상위 컴포넌트의 데이터 이름"
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- <app-header v-bind:프롭스 속성 이름="상위 컴포넌트의 데이터 이름"></app-header> -->
      <app-header v-bind:propsdata="message"></app-header>
      <app-content v-bind:number="number"></app-content>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let appHeader = {
        template: '<h1>{{propsdata}}</h1>',
        props: ['propsdata'],
      };

      let appContent = {
        template: '<div>{{number}}</div>',
        props: ['number'],
      };

      new Vue({
        el: '#app',
        components: {
          'app-header': appHeader,
          'app-content': appContent,
        },
        data: {
          message: 'hi ',
          number: 10,
        },
      });
    </script>
  </body>
</html>

Event Emit

  • Vue에서는 하위 컴포넌트에서 상위 컴포넌트로 Event라는것을 보낼 수 있다.
  • 방법은 아래와 같다.
    • 1) 컴포넌트 template에 v-on:click="passEvent" 이런식으로 태그에 달아주고, 하위컴포넌트 methods 객체에 해당 passEvent 메서드를 선언하면된다.
    • 2) 컴포넌트 호출 부에 v-on:발생한 이벤트 이름="상위 컴포넌트의 메서드 이름" 이런식으로 달아주고, Vue 인스턴스에 methods를 선언한다.
  • 이렇게 하면 하위 컴포넌트에서 발생하여 Emit으로 끌어올린 Event를 상위로 버블링 시킬 수 있고, 상위 컴포넌트에서 그 이벤트를 캡쳐해서 원하는 메서드를 실행시킬 수 있다.
  • React에서는 props로 setState를 내려주거나 function을 내려주는 것이 흔한 패턴이었는데, Vue에선 굳이 그럴 필요가 없이 이벤트를 올려주면 상위 컴포넌트에서 해당 이벤트를 리슨하여 기능을 작동시킬 수 있다.
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- <app-header v-on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메서드 이름"></app-header> -->
      <app-header v-on:pass="logText"></app-header>
      <h2>{{number}}</h2>
      <app-content v-on:increase="increaseNumber"></app-content>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <script>
      let appHeader = {
        template: '<button v-on:click="passEvent">Click me</button>',
        methods: {
          passEvent: function () {
            this.$emit('pass');
          },
        },
      };

      let appContent = {
        template: '<div><button v-on:click="addNumber">Add</button></div>',
        methods: {
          addNumber: function () {
            this.$emit('increase');
          },
        },
      };

      new Vue({
        el: '#app',
        components: {
          'app-header': appHeader,
          'app-content': appContent,
        },
        methods: {
          logText: function () {
            console.log('hi');
          },
          increaseNumber: function () {
            this.number++;
          },
        },
        data: {
          number: 10,
        },
      });
    </script>
  </body>
</html>

여담

  • 이벤트 핸들러 넣으니까 코드가 너무 더러워졌다. 해결방안이 있겠지.

댓글