728x90
반응형

지난 글에 이어서 컴포넌트에 대하여 알아보도록 하겠습니다. 이번에는 컴포넌트 간 통신에 대하여 자세히 알아 봅니다.

 

컴포넌트

- 컴포넌트 통신하기

. 컴포넌트 간 통신과 유효범위

뷰는 컴포넌트로 화면을 구성하므로 같은 웹 페이지라도 데이터를 공유할 수 없습니다. 그 이유는 컴포넌트마다 자체적으로 고유한 유효 범위를 갖기 때문입니다. 이것은 뷰 프레임워크 내부적으로 정의된 특징이라고 합니다. 각 컴포넌트의 유효 범위가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수가 없다는 것 입니다.

뷰 프레임워크 자체에서 정의한 컴포넌트 데이터 전달 방법을 따라야 값을 참조할 수 있습니다. 가장 기본적인 데이터 전달 방법은 바로 상위(부모) - 하위(자식) 컴포넌트 간의 데이터 전달 방법입니다.

 |==============|  -- (props 전달) →  |=============|
 | 상위 컴포넌트 |                                      | 하위 컴포넌트 |
 |==============|   (이벤트 발생) -- |=============|

상위에서 하위로는 props라는 특별한 속성을 전달합니다. 그리고 하위에서 상위로는 기본적으로 이벤트만 전달할 수 있습니다.

 

. 상위에서 하위 컴포넌트로 데이터 전달하기

props는 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때 사용하는 속성입니다. props 형태는 아래와 같습니다. 아래의 형태를 하위 컴포넌트 속성에 정의를 합니다.

Vue.component('child-component', {
   props : ['props 속성 이름']
});

상위 컴포넌트의 HTML 코드에 등록된 child-component 컴포넌트 태그에 v-bind 속성을 추가합니다. v-bind 속성의 왼쪽 값은 하위 컴포넌트에서 정의한 props 속성을 넣고, 오른쪽 값은 하위 컴포넌트에 전달할 상위 컴포넌트의 data 속성을 지정합니다.

<child-component v-bind:props 속성이름="상위 컴포넌트의 data 속성"></child-component>

아래는 예제 코드 입니다.

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Vue component registration</title>
  </head>
  <body>
    <div id="app">
      <h3>app 인스턴스 영역</h3>
      <!-- // 4 -->
      <child-component v-bind:propsdata="message"></child-component>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>

// 2
      Vue.component('child-component',{
        // 3
        props : ['propsdata'],
        // 5
        template : '<p>{{ propsdata }}</p>'
      });

// 1
      new Vue({
        el:'#app',
        data: {
          message : 'Test Vue! 상위 컴포넌트를 통한 통신'
        }
      });

    </script>
  </body>
</html>

아래는 실행 화면입니다.

동작 과정 (코드에서 주석에 달린 번호를 참고하십시오)

  1. new Vue() 로 인스턴스를 생성
  2. Vue.component() 를 이용하여 하위 컴포넌트 child-component를 등록
  3. child-component 내용에 props 속성으로 propsdata 를 정의
  4. HTML에 컴포넌트 태그 추가
    v-bind 속성 propsdata="message" 는 상위 컴포넌트의 message 속성 값을 하위 컴포넌트의 propsdata로 전달 함
  5. child-component 의 template 속성에 정의된 값으로 message 에 정의된 텍스트가 됨

여기서 인스턴스가 상위 컴포넌트가 되며, child-component가 하위 컴포넌트가 됩니다. 이렇게 새 컴포넌트를 등록한 인스턴스를 최상위 첨포넌트라고도 부릅니다.

. 하위에서 상위 컴포넌트로 이벤트 전달하기

이번에는 하위 컴포넌트에서 상위 컴포넌트로 이벤트를 발생시켜 보겠습니다. 상위 컴포넌트는 하위 컴포넌트의 특정 이벤트가 발생하기를 기다리고 있다가 하위 컴포넌트에서 특정 이벤트가 발생하면 상위 컴포넌트에서 해당 이벤트를 수신하여 상위 컴포넌트의 메서드를 호출하는 방식 입니다.

이벤트 발생과 수신은 $emit() 과 v-on: 속성을 사용하여 구현합니다. 각각의 형식은 아래와 같습니다.

// 이벤트 발생
this.$emit('이벤트명');
// 이벤트 수신
<child-component v-on:이벤트명="상위 컴포넌트의 메서드명"></child-component>

$emit()을 호출하면 괄호 안에 정의된 이벤트가 발생합니다. $emit()을 호출하는 위치는 일반적으로 하위 컴포넌트의 특정 메스트 내부입니다. 이때 this는 하위 컴포넌트를 가리킵니다.

호출한 이벤트는 하위 컴포넌트를 등록하는 태그에서 v-on:으로 받습니다. 속성의 값에 이벤트가 발생했을 때 호출될 상위 컴포넌트의 메서드를 지정합니다. 아래는 예제 코드입니다.

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Vue component registration</title>
  </head>
  <body>
    <div id="app">
      <h3>app 인스턴스 영역</h3>
      <!-- // 3 -->
      <child-component v-on:show-log="printText"></child-component>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>

      Vue.component('child-component',{
        // 1
        template : '<button v-on:click="showLog">show</button>',
        // 2
        methods: {
          showLog: function(){
            this.$emit('show-log');
          }
        }
      });

      new Vue({
        el:'#app',
        data: {
          message : 'Test Vue!'
        },
        // 4
        methods:{
          printText: function(){
            console.log("이벤트 받음");
          }
        }
      });

    </script>
  </body>
</html>

아래는 실행결과 입니다.

 

동작 과정 (코드에서 주석에 달린 번호를 참고하십시오)

  1. [show] 버튼을 클릭하면 클릭 이벤트 showLog() 메서드가 실행
  2. showLog() 메서트 안에서 this.$emit('show-log') 가 실행되어 show-log 이벤트가 발생
  3. show-log 이벤트는 <child-component> 에 정의한 v-on:show-log 에 전달되고 지정한 printText() 를 실행
  4. printText() 에서 콘솔에 로그를 출력

뷰에서는 미리 정의해 놓은 데이터 전달 방식에 따라 일관된 구조로 애플리케이션을 작성하게 됩니다. 그러므로 개발자 개개인의 스타일대로 구정되지 않고, 애플리케이션의 모두 동일한 데이터 흐름을 갖습니다. 이는 다른 사람의 코드를 빠르게 파악할 수 있어서 협업하기에 좋습니다.

 

. 이벤트 버스

상위에서 하위로 props를 전달하고 하위에서 상위로 이벤트를 전달하는 방법을 알아보았습니다. 이번에는 같은 레벨에 있는 컴포넌트 혹은 관계가 없는 컴포넌트 간 통신은 어떻게 해야할까요?  이럴 경우 이벤트 버스를 활용하면 원하는 컴포넌트에 바로 데이터를 전달할 수 있습니다. 이벤트 버스의 형식은 다음과 같습니다.

// 이벤트 버스를 위한 추가 인스턴스 1개 생성
var eventBus = new Vue();
// 이벤트를 보내는 컴포넌트
methods: {
    메서트명: function(){
        eventBus.$emit('이벤트명', 데이터);
    }
}
// 이벤트를 받는 컴포넌트
methods: {
    created : function(){
       eventBus.$on('이벤트명', function(데이터){
           ...
        });
    }
}

위의 형식을 사용하여 이벤트 버스를 구현하는 코드입니다.

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Vue component registration</title>
  </head>
  <body>
    <div id="app">
      <h3>app 인스턴스 영역</h3>
      <child-component></child-component>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      // 1
      var eventBus = new Vue();

      Vue.component('child-component',{
        // 2
        template : '<div>하위 컴포넌트 영역 : <button v-on:click="showLog">show</button></div>',
        methods: {
          showLog: function(){
            console.log("이벤트 전송 start");
            eventBus.$emit('sendEventBus', 100);
            console.log("이벤트 전송 end");
          }
        }
      });

      var app = new Vue({
        el:'#app',
        created: function(){
          // 3
          eventBus.$on('sendEventBus', function(value){
            console.log("이벤트 전달 받음. 데이터:",value);
          });
        }
      });

    </script>
  </body>
</html>

실행 결과입니다.

 

동작 과정 (코드에서 주석에 달린 번호를 참고하십시오)

  1. 이벤트 버스로 활용할 새 인스턴스 1개를 생성
  2. 하위 컴포넌트에 template 속성과 methods 속성을 정의, showLog() 메서드 안에서 eventBus.$emit('sendEventBus', 100)를 선언하여 sendEventBus 라는 이벤트를 발생. 또한, 데이터 100이라는 숫자도 전달
  3. 상위 컴포넌트의 created 라이프 사이클 훅에 eventBus.$on() 으로 이벤트를 받는 로직 선언. 발생한 이벤트를 수신할때 데이터 100 도 넘겨받아 로그로 출력

이벤트 버스를 활용하면 props 속성을 이용하지 않고도 원하는 컴포넌트 간의 직접적으로 데이터를 전달할 수 있어 편리하지만 컴포넌트가 많아지면 어디서 어디로 보냈는지 관리가 되지 않는 문제가 발생할 수 있습니다.

 

지금까지 인스턴스와 컴포넌트에 관련하여 학습하였습니다. 가장 기본이 되는 개념이기때문에 확실히 익히고 넘어가야 할 것 입니다.

 

2021.06.22 - [Programe Note/Vue.js] - [Vue.js] 인스턴스 와 컴포넌트 개념(1)

 

[Vue.js] 인스턴스 와 컴포넌트 개념(1)

간단한 화면부터 복잡한 화면까지, 멋진 화면을 만들기 위해서는 UI를 생각해 봐야합니다. 이를 설계라고 하는데,  인스턴스와 컴포넌트가 있어야 합니다. 이 두가지에 대해서 알아보도록 하겠

tylee82.tistory.com

2021.06.22 - [Programe Note/Vue.js] - [Vue.js] 인스턴스 와 컴포넌트 개념(2)

 

[Vue.js] 인스턴스 와 컴포넌트 개념(2)

컴포넌트 컴포넌트란 조합하여 화면을 구성할 수 있는 블록을 의미합니다. 화면을 빠르게 구조화하여 일괄적인 패턴으로 개발할 수 있습니다. 화면의 영역을 컴포넌트로 쪼개서 재활용할 수 있

tylee82.tistory.com

 

728x90
반응형

+ Recent posts