본문 바로가기
개발/Vue.js

Vue.js 컴포넌트와 컴포넌트 통신

by 궁즉변 변즉통 통즉구 2022. 3. 19.
반응형

Vue 컴포넌트

  • 화면을 조합해서 구성할 수 있게 블럭형태로 분할 된 화면영역(Component)을 의미
  • 컴포넌트 간의 관계는 일반적으로 Tree 구조
  • 화면 구성요소의 재활용
  • 각 컴포넌트는 각각의 고유한 유효범위를 가짐

전역(Global) 컴포넌트

  • Vue 변수를 사용해서 등록하는 컴포넌트
  • 모든 인스턴스에서 접근 가능
  • 일반적으로 전역 컴포넌트를 선언해서 사용하는 경우는 거의 없음, 대부분 플러그인, 3thParty 라이브러리 사용 시 활용
  Vue.component("global-component", {
    template: "<h1>Content</h1>",
  });

 

 지역(Local) 컴폰너트

  •  Vue 인스턴스에서 'components' 속성을 사용해서 정의
  • 해당 인스턴스의 유효범위 내에서만 사용 가능
new Vue({
    el: "#app",
    components: {
      // '#app' html엘리먼트 내에서만 사용 가능
      "local-component": {
        template: "<div>Content</div>",
      },
    },
});

 

컴포넌트 간 통신 

  • Vue인스턴스 고유한 유효범위로 다른 인스턴스의 값을 직접 접근 불가
  • Vue의 기본 데이터 통신 방식
    - '상위 컴포넌트 -> 하위 컴포넌트' [데이터] 전달
    - '하위 컴포넌트 -> 상위 컴포넌트' [이벤트] 전달
    =>
    데이터의 흐름을 쉽게 추적 가능하고 관리가 용이

[Props] 상위 컴포넌트 -> 하위 컴포넌트 

<body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <div id="app">
      <app-header v-bind:propsdata="message"></app-header>
    </div>
    <script>
      var appHeader = {
        template: "<h1>{{propsdata}}</h1>",
        props: ["propsdata"],
      };
      new Vue({
        el: "#app",
        components: {
          "app-header": appHeader,
        },
        data: {
          message: "hi",
        },
      });
    </script>
  </body>

상위컴포넌트의 'message' 데이터를 하위컴포넌트로 전달하여 화면에 출력.

<app-header v-bind:propsdata="message"></app-header> 에서 상위컴포넌트의 message를 하위컴포넌트의 propsdata로 전달. 

 

[emit] 하위 컴포넌트 -> 상위 컴포넌트 샘플 

<body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <div id="app">
      {{ num }}
      <!-- 
        이벤트 수신  
        <app-header v-on:하위컴포넌트에서 발생하는 이벤트:상위컴포넌트의 메소드명></app-header> 
       -->
      <app-content v-on:pass-add="addNum"></app-content>
    </div>

    <script>
      var appContent = {
        template: "<button v-on:click='addNumber'>add</button>",
        methods: {
          addNumber: function () {
            this.$emit("pass-add");  // 이벤트 발생
          },
        },
      };
      new Vue({
        el: "#app",
        components: {
          "app-content": appContent,
        },
        methods: {
          addNum: function () {
            console.log(this.num);
            this.num++;
          },
        },
        data: {
          num: 10,
        },
      });
    </script>
  </body>

하위컴포넌트에서 버튼 클릭 시 $emit으로 "pass-add"라는 이름의 이벤트를 발생 시키면
=>  <app-content v-on:pass-add="addNum"></app-content>에서 pass-add이벤트에 대해 상위컴포넌트의 addNum 메소드 호출 후 숫자 +1 처리

 

 

같은 레벨 컴포넌트 간 통신

출처: https://sas-study.tistory.com/236

컴포넌트 A -> 컴포넌트 B로 데이터 전달 할 경우

A컴포넌트 -> (emit) -> 상위컴포넌트 -> (props) -> B 하위컴포넌트

 

<body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <div id="app">
      <app-header v-bind:propsdata="num"></app-header>
      <app-content v-on:pass="deliverNum"></app-content>
    </div>
    <script>
      var appHeader = {
        template: "<div> {{ propsdata }}</div>",
        props: ["propsdata"],
      };
      var appContent = {
        template: `<div>
                        <button v-on:click="passNum">버튼</button>
                    </div>`,
        methods: {
          passNum() {
            this.$emit("pass", 10);
          },
        },
      };
      new Vue({
        el: "#app",
        components: {
          "app-header": appHeader,
          "app-content": appContent,
        },
        data: {
          num: 0,
        },
        methods: {
          deliverNum(value) {
            this.num = value;
          },
        },
      });
    </script>
  </body>

appContent 컴포넌트에서 버튼 클릭 시 $emit("pass", 10) 이벤트와 값을 넘김

=> <app-content v-on:pass="deliverNum"></app-content> 에서 pass이벤트 받아서 상위컴포넌트의 deliverNum메소드 호출

=> deliverNum()에서 상위컴포넌트 data의 num 변경

=> <app-header v-bind:propsdata="num"></app-header> 에서 num값이 appHeader컴포넌트의 propsdata로 바인딩 됨

=> appHeader컴포넌트의 propsdata 화면 출력

 

EventBus 사용

  • 상하위 기본 데이터 전송 규칙과 관계없이 지정한 컴포넌트 간에 데이터를 주고 받을 수 있는 방법
  • EventBus용 별도 Vue 인스턴스 사용해서 이벤트 발생($emit) 및 수신 처리($on)
  • 컴포넌트 간 직접 통신으로 편리하지만 많아질 경우 데이터 관리 어려움 => 상태관리도구 필요(Vuex)
<body>
    <body>
      <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
      <div id="app">
        <app-header></app-header>
        <app-content></app-content>
      </div>
      <script>
        // EventBus 용 별도 Vue 인스턴스 생성
        var eventBus = new Vue();
        var appHeader = {
          template: "<div>header</div>",
          // created에서 EventBus 이벤트 리스너 설정
          created() {
            eventBus.$on("pass", function (value) {
              console.log(value);
            });
          },
        };
        var appContent = {
          template: `<div>
                            <button v-on:click="passNum">버튼</button>
                        </div>`,
          methods: {
            passNum() {
              eventBus.$emit("pass", 10); // EventBus로 이벤트 발생
            },
          },
        };
        new Vue({
          el: "#app",
          components: {
            "app-header": appHeader,
            "app-content": appContent,
          },
        });
      </script>
</body>

appContent 컴포넌트와 appHeader컴포넌트 직접 통신

var eventBus = new Vue(); 로 이벤트 버스용 인스턴스 생성

=> appContent컴포넌트에서 버튼 클릭 시 eventBus.$emit("pass", 10) 이벤트와 값을 넘김

=> appHeader컴포넌트 created 라이프사이클 훅에서  eventBus.$on()으로 "pass"이벤트 수신 처리

 

 

반응형

댓글