Vue.js

[Vue.js] 입문 - 뷰 컴포넌트 통신

723poil 2022. 2. 22. 01:20

상(부모)·하위(자식) 컴포넌트 관계

컴포넌트는 각각 고유한 유효 범위를 가지고 있기 때문에 직접 다른 컴포넌트의 값을 참조할 수 없습니다.
그렇기에 뷰에서 정의한 데이터 전달 방법을 사용해야 합니다.
가장 기본적인 데이터 전달 방법으로 부모-자식 컴포넌트 간의 데이터 전달 방법이 있습니다.

부모 -> 자식 데이터 전달

props 라는 속성을 전달하는 방법

Vue.component('child-component', {
	props: ['props 속성 이름'],
});
<child-component v-bind:props 속성 이름="상위 컴포넌트의 data 속성"></child-component>

v-bind 속성의 왼쪽 값으로 하위 컴포넌트에서 정의한 props 속성을 넣고, 오른쪽 값으로 하위 컴포넌트에 전달할 상위 컴포넌트의 data 속성을 지정

 

<html>
	<body>
    	<div id="app">
            <child-component v-bind:propsdata="message"></child-component>
        </div>
     	<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
        <script>
            Vue.component('child-component', {
                props: ['propsdata'],
                template: '<p>{{ propsdata }}</p>',
            });

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

 

 


자식 -> 부모 이벤트 전달

자식 컴포넌트에서 부모 컴포넌트로의 통신은 이벤트를 발생시켜 부모 컴포넌트로 신호를 보내면 됩니다.

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

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

 

<html>
	<body>
    	<div id="app">
            <child-component v-on:show-log="printText"></child-component>
        </div>
     	<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
        <script>
            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>

클릭 시

app 컴포넌트 하위에 'child-component' 컴포넌트를 넣은 후, 버튼을 통해 showLog 로직이 발생하도록 설정합니다.

버튼 클릭 시 showLog 메서드가 실행되고, 'show-log' 이벤트를 발생시켜 상위 컴포넌트인 app 컴포넌트의 printText 메서드가 실행이 됩니다.

 

 

 


관계 없는 컴포넌트 간 통신 - 이벤트 버스

이벤트 버스는 개발자가 지정한 3개의 컴포넌트 간에 데이터를 주고받을 수 있는 방법입니다.
이벤트 버스를 이용하면 상위-하위 컴포넌트 관계를 유지하고 있지 않아도 데이터를 한 컴포넌트에서 다른 컴포넌트로 전달할 수 있습니다.
var eventBus = new Vue(); // 이벤트 버스를 위한 추가 인스턴스 1개 생성
methods: { // 이벤트를 보내는 컴포넌트
 	메서드명: function() {
    	evnetBus.$emit('이벤트명', 데이터);
    }
}
methods: { // 이벤트를 받는 컴포넌트
    created: function() {
    	eventBus.$on('이벤트명', function(데이터) {
    	...
    	});
    }
}

 

<html>
	<body>
    	<div id="app">
            <child-component></child-component>
        </div>
     	<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
        <script>
            var eventBus = new Vue();

            Vue.component('child-component', {
                template: '<div>하위 컴포넌트 영역입니다.<br><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()가 실행되었을 때 eventBus의 이벤트가 발생합니다. 발생한 이벤트는 상위 컴포넌트의 created()에 있는 eventBus.$on()에서 전달받아 메서드가 실행이 됩니다.