상세 컨텐츠

본문 제목

[Vue3] EventBus 사용방법

VUE3

by happynuri 2024. 4. 26. 17:42

본문

EventBus는 소규모 프로젝트에서 사용하기 적합하고, 대규모 프로젝트에서는 vuex를 사용한다는데 

 

오늘은 EventBus를 알아 보았다.

 

컴포넌트A와 컴포넌트B 가 부모 자식 간일때 props를 전달하거나 emit를 이용하는 것 정도는 할 수 있는데 

 

EventBus가 무엇인지 모르는 사람은 이 글이 도움이 될것이다.

 

 

props 드릴링이라고 할머니.vue , 엄마.vue, 자식.vue 가 있을 경우에는 

 

할머니.vus에서 자식.vue로 값을 보내거나 할 경우는 필요 없는 props 를 엄마.vue 가 가지고 있어야 하는 불편한 상황을

 

 props 드릴링이라고 하고, 그 상황을 피하기 위해서 

 

형제 간의 vue나 조상 vue에서 한참 밑의 vue 간에 이벤트 통신을 위해서 EventBus를 사용한다.

 

구글링 하면 vue2에서 사용하는 방법은 많이 나와 있으나, vue3가 정보가 내가 볼땐 별로? 없는 것 같아서 정리를 해 본다.

 

 

Vue3에서는 Vue2에서 사용하는 $on, $off, $once가 사라졌고 사용하기 위해서는  mitt를 다운 받아서 구현 할 수 있다.

 

class를 직접 정의해서 사용해도 되지만 굳이? 그래서 있는것을 사용해 보기로 한다.

 

아래와 같이 설치를 한다.

npm install --save mitt

 

 

 

main.ts (전역으로 선언 해주는것)

const app = createApp(App)
import mitt from 'mitt'
/** 이벤트 버스를 선언 */
const emitter = mitt()
app.config.globalProperties.emitter = emitter

 

 

할머니.vue  emitFunction ()는 onMounted 할때 호출을 해 주고 enterKeyFunction은 클릭시 마다 호출을 한다.

<template>
  <div>
    <button @click="enterKeyFunction">부모에서 선언한 버튼 인데 다른 컴포넌트로 값을 보낸다.</button>
    <child></child>
  </div>
</template>
<script setup lang="ts">
import {ref, reactive, onMounted , provide , inject, readonly} from 'vue';
import child from './child.vue'
import { getCurrentInstance } from 'vue'
const app = getCurrentInstance()
const bus = app?.appContext.config.globalProperties.emitter
 

const interfaceA1 = ref({}as interfaceA)
interface interfaceA {
  item: string
  type: string
}

const emitFunction = (val: number) =>{  
console.log('[emitFunction1] param =',val)
val = val + 1
console.log("[emitFunction2] param +1 = ", val)
interfaceA1.value =  {item: "음료수" , type:"콜라" + val}
console.log("[emitFunction3]", interfaceA1.value.type)
bus.emit("emitFunction", interfaceA1.value) /* 어떤 행위를 전달을 하면 */
}
 
 

const cnt = ref(1)
const enterKeyFunction = ()=>{
  cnt.value = cnt.value + 1
  console.log('cnt=',cnt.value)
bus.emit('enterKeyFunction', {'aa': 'aa의값' + cnt.value , 'bb' : 'bb의 값'+ cnt.value})

}

 

 

param을 보낼때는 변수 1개에 넣어야 하는 것 같은데 위처럼 interface 하나에 여러개의 키값을 뭉쳐서 넣어 줘도 수신이 가능하다

 

child.vue  : grandChild를 포함만 해서 할머니와 손자의 통신을 보자.

<template>
  <div>   
        자식의 result값 : {{ result }}
        <grandChild></grandChild>
  </div>
</template>

<script setup lang="ts">
import grandChild from './grandChild.vue';

 

 

손자.vue

 

<template>
  <div>
  </div>
</template>

<script setup lang="ts">
import {ref, reactive, onMounted , provide , inject , getCurrentInstance} from 'vue';
 
const app = getCurrentInstance()
const bus = app?.appContext.config.globalProperties.emitter


interface interfaceA {
  item: string
  type: string
}

bus.on("emitFunction", (obj1) => {
  let interfaceA1 = ref({}as interfaceA)
  interfaceA1.value = obj1
  console.log("수신된 interfaceA1.item:", interfaceA1.value.item)  
})


bus.on("enterKeyFunction", (obj1) => {
console.log("수신된 obj [aa]:", obj1.aa , ", [bb]:", obj1.bb)  
})

 

npm run dev로 실행을 해 보면 onMounted에서 실행된 

emitFunction () 이 호출이 되고, 손자.vue에서 음료수 라는 값을 수신 받았다.

 

버튼을 클릭을 하면 cnt값이 변경 된것이 추가 되면서 제공 되고, 손자가 잘 수신 하는것을 확인 할 수 있다.

 

 

기본이지만, 값을 받을때는 같은 interface 형으로 받아서 처리를 해야 하는 것은 Tip

 

관련글 더보기

댓글 영역