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()에서 전달받아 메서드가 실행이 됩니다.