Vue의 기본적인 컴포넌트 관계인 상-하위 컴포넌트간 통신은 props와 이벤트를 통해서 이뤄졌다.
하지만 동일한 level의 컴포넌트 가령 아래 그림처럼 하나의 상위 컴포넌트와 두개의 하위 컴포넌트 구조에서
두 하위 컴포넌트끼리 통신을 해야하는 상황이라면??
Vue.js는 기본적으로 상위 -> 하위로의 데이터 전달 구조를 갖기 때문에 이러한 경우 props를 통해 다음과 같은 과정을 거쳐야 한다.
즉, 결국 상위 컴포넌트를 강제로 거쳐야하는 상황이 발생한다.
이러한 경우 불필요한 컴포넌트를 만들어야하는 상황이 오기 때문에 이를 해결하기 위한 방법으로 Event Bus가 있다.
Event Bus : 컴포넌트 계층 구조와 관계 없어 두 컴포넌트 사이에 데이터를 전달할 수 있다.
기본적인 Event Bus 형식으로는 $emit(), $on()이 있다.
Event Bus를 사용하려면 기본적으로 애플리케이션 로직을 담는 Vue 인스턴스와 별도로 새로운 Vue 인스턴스를 생성하여 import해서 사용해야한다.
다음과 같이 Event Bus 및 컴포넌트를 정의했다.
요구사항은 다음과 같다.
[화면]
코드 구현 과정은 다음과 같다.
[App.vue]
<template>
<v-app id="inspire">
<v-main>
<InputArea></InputArea>
<Home v-bind:linkInfo="path"></Home>
</v-main>
</v-app>
</template>
<script>
import Home from "@/components/preset/Home";
import InputArea from "@/components/preset/InputArea";
export default {
name: 'App',
components: {
Home,
InputArea
},
data: () => ({
})
};
</script>
<style scoped>
</style>
InputArea와 Home 컴포넌트는 App 컴포넌트를 상위로 갖는 동일한 레벨의 컴포넌트다.
[eventBus.js]
EventBus를 위한 Vue 인스턴스를 생성 후 export 한다.
import Vue from 'vue';
const EventBus = new Vue();
export default EventBus;
[InputArea.vue]
<template>
<v-container fluid>
<!-- v-model을 통해 input에 입력되는 value를 data 속성에 바인딩 -->
<v-text-field label="검색바" v-model="inputText"></v-text-field>
<v-btn v-on:click="transferText">전송</v-btn>
<!-- 전송버튼 click 시 transferText 라는 이벤트 송신 메서드 실행 -->
</v-container>
</template>
<script>
import EventBus from "@/eventBus";
export default {
data () {
return {
inputText: ''
}
},
name: "InputArea",
methods: {
transferText: function () {
console.log('이벤트 송신');
EventBus.$emit('transferText', this.inputText); //이벤트명, 데이터 정의
}
}
}
</script>
[Home.vue]
<template>
<v-container
class="fill-height"
fluid
>
<v-row
align="center"
justify="center"
>
<v-col class="text-center">
<!-- v-bind를 통한 href 속성 변경 -->
<v-btn :href="path">네이버연결</v-btn>
</v-col>
</v-row>
</v-container>
</template>
<script>
import EventBus from "@/eventBus"; // 생성한 EventBus import
export default {
data() {
return {
path: '' //최초 rendering 시 기본 값
}
},
created() {
// eventBus를 통해 transferText라는 이벤트를 수신하고 넘어온 res라는 데이터를 data 속성인 path에 연결
EventBus.$on('transferText', (res) => {
console.log('이벤트 수신');
this.path = res;
});
}
}
</script>
[결과]
사진에서처럼 eventBus를 통해 전달받은 데이터를 네이버연결버튼 href 속성에 잘 변경한 것을 알 수 있다.
vue-devtools를 통해서도 확인해보면 아래와 같이 Event가 잘 발생하는 것을 알 수 있다.
[InputArea에서 클릭시 transferText 이벤트 발생]
[Home에 data 속성 변경 확인]
지금까지 EventBus를 통한 두 컴포넌트 간 데이터 전달과정을 알아봤다.
Vue.js 공식 문서에 $emit, $on과 같은 이벤트 관련 인스턴스 메소드들이 정리되어 있으니 참고하면 좋을 것 같다.
[참고]
[Vue.js] 3. props와 event로 컴포넌트 통신(상위 <-> 하위) (0) | 2020.08.13 |
---|---|
[Vue.js] 2. Vue 프로젝트 디렉토리 구조 (0) | 2020.08.12 |
[Vue.js] 1. Vue.js 개발 환경 설정(with IntelliJ) (0) | 2020.08.12 |