[Vue.js] Vue 컴포넌트간의 통신!

컴포넌트간 통신

- 뷰의 경우는 컴포넌트로 화면을 구성하기 때문에 같은 웹페이지라도 데이터를 공유할 수 없는 경우가 많다.

- 각 컴포넌트들의 scope(유효범위)가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수가 없다.

 

상/하위 컴포넌트 관계

- 뷰의 가장 기본적인 데이터 전달방법.

 

상/하위 컴포넌트 통신 방식

- 상위(Parent) 컴포넌트에서 props라는 속성으로 전달.

- props : 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때 사용하는 속성. 하위 컴포넌트의 속성에 정의.

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

- 상위 컴포넌트의 HTML 코드에 정의된 child-component 태그에 v-bind 속성을 정의.

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

 

예제로 확인

- 뷰인스턴스 자체가 상위 컴포넌트가 됨.

<!DOCTYPE html>
<html lang="ko" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
    <div id="app">
      <child-component v-bind:propsdataa="message"></child-component>
    </div>
    <script>
      Vue.component('child-component',{
        props:['propsdataa'],
        template:'<p>{{propsdataa}}</p>'
      });

      new Vue({
        el:'#app',
        data:{
          message:'Hello Vue! passed from Parent Component'
        }
      });
    </script>
  </body>
</html>

- 상위 컴포넌트의 message 속성을 하위 컴포넌트에 props로 데이터를 전달하여 메시지를 출력하는 코드.

- v-bind 속성에는 자식컴포넌트의 props 속성명을 쓰고 = 다음 ""(따옴표)안에 상위 컴포넌트로부터 받을 속성명을 기재.

- child-component는 상위 컴포넌트의 message를 받는 태그이므로 message에 있는 문자열 자체가 <child-component> 태그가 됨.

 

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

- 이벤트를 발생시켜 상위 컴포넌트에 신호를 보냄.

- 상위 컴포넌트에서 하위 컴포넌트의 특정 이벤트가 발생하기를 기다리다가 이벤트가 발생하면 상위 컴포넌트에서 이벤트를 수신하여 상위 컴포넌트의 메서드를 호출하는 방식!.... 어렵다...

- 이벤트 발생은 $emit() / 수신은 v-on 속성을 이용합니다.

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

- $emit()을 호출하면 괄호안에 정의된 이벤트가 발생됨. 주로 하위컴포넌트의 특정 메서드 내부에서 호출.(데이터를 상위에 전달하기 위해)

- 호출한 이벤트를 v-on 속성으로 받음. 호출될 상위 메소드명 지정.

 

이벤트 발생시키고 수신하기 예제로 보기

<!DOCTYPE html>
<html lang="ko" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>sss</title>
  </head>
  <body>
      <script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
      <div id="app">
        <child-component v-on:show-log="printText"></child-component>
      </div>

      <script type="text/javascript">

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

        var app = new Vue({
          el:'#app',
          data:{
            message : 'Hello Vue! passed from Parent Component'
          },
          methods : {
            printText:function(){
              console.log("received an event");
            }
          }
        });

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

- 가장먼저 브라우저로 코드를 실행했을 때 show라는 버튼이 보일 것.

- 버튼을 누르면 click 이벤트가 발생되고(버튼은 click 이벤트만 바라보고 있음), 자신의 methods 속성에 있는 showLog에 정의된 함수를 실행하게됨.

- showLog 함수는 show-log 이벤트를 발생시키는데 이는 <child-component> 태그가 기다리고 있는 이벤트임

- 그래서 상위 컴포넌트인 뷰인스턴스에 정의된 printText 메소드를 실행해서 "received an event"라는 콘솔 메시지가 출력되는 것을 볼 수 있음.

 

같은 레벨의 컴포넌트 간의 통신

동일 레벨 컴포넌트간의 통신

- A에서 B로 전달하려면 상위 컴포넌트에 이벤트로 값을 전달하고 하위 컴포넌트에 props를 내려보내야함.

- 다른 컴포넌트의 값을 직접 참조할 수는 없음!! 

- 그러나! 이벤트 버스라는 방법으로 통신이 가능함.

 

이벤트 버스

- 개발자가 2개의 컴포넌트 간에 데이터를 주고받을 수 있는 방법.

- 이렇게 바로 전달할 수 있음.

- 이벤트 버스에 해당하는 인스턴스를 생성.

// 이벤트 버스를 위한 추가 인스턴스 1개 생성
var eventBus = new Vue();

- 보내는 컴포넌트에 $emit() / 받는 컴포넌트에 $on() 각각 정의해놓는다.

// 이벤트를 보내는 컴포넌트
methods:{
	methodName : function(){
    	eventBus.$emit('eventName',"abc");
    }
}
//이벤트를 받는 컴포넌트
methods:{
	created:function(){
    	eventBus.$on('eventName',function(data){
        	console.log(data); //abc
        });
    }
}

 

구현 소스 보기

<!DOCTYPE html>
<html lang="ko" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>ff</title>
  </head>
  <body>
      <script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
      <div id="app">
        <child-component></child-component>
      </div>

      <script type="text/javascript">
        var eventBus = new Vue();
        Vue.component('child-component',{
          template:'<div>하위 컴포넌트 영역입니다. <button v-on:click="showLog">show</button></div>',
          methods:{
            showLog:function(){
              eventBus.$emit('triggerEventBus',100);
            }
          }
        });

        var app = new Vue({
          el:'#app',
          created:function(){
            eventBus.$on('triggerEventBus',function(value){
              console.log("이벤트를 전달받음. 전달받은 값:"+value);
            });
          }
        });
      </script>
  </body>
</html>

- 이벤트 버스 인스턴스를 하나 생성.

- show라는 버튼이 있는데 클릭하면 하위 컴포넌트의 showLog 함수가 실행되면서 'triggerEventBus'라는 이벤트와 100이라는 값이 파라미터로 넘어가게됨.

- 뷰 인스턴스에서는 'triggerEventBus' 이벤트를 수신하여 value 변수로 100값을 할당받고 출력하면

- 이벤트를 전달받음. 전달받은 값: 100 <<< 출력결과.

 

장점 / 단점

- 이렇게 이벤트버스를 활용하면 props 속성을 이용하지 않고도 원하는 컴포넌트간에 직접적으로 데이터를 전달할 수 있어편리함.

- 하지만 컴포넌트가 많아지면 어디서 어디로 보냈는지 관리가 되지않는 문제 발생 -> 이를 해결하기 위해서 뷰엑스라는 상태관리도구가 필요함.

댓글

Designed by JB FACTORY