프로그래밍/Js

Vue 3에서 mitt를 사용하여 이벤트 핸들러 중복 실행 방지하기

소행성왕자 2024. 6. 13. 20:59

Vue 3 애플리케이션에서 여러 컴포넌트에서 동일한 컴포넌트를 사용하면서 mitt를 활용한 이벤트 핸들러가 중복 실행되는 문제를 해결하는 방법을 소개합니다.

이 글에서는 전역 이벤트 버스를 사용하여 이벤트 리스너가 한 번만 등록되도록 하는 방법을 설명합니다.

문제상황

여러 컴포넌트(order.vue, rfOrder.vue, marketWatch_spot.vue, marketWatch_exchange.vue)에서 동일한 컴포넌트(currencyMaster.vue)를 사용하고 있습니다.

mitt를 사용하여 이벤트(FAReceive)를 관리하는데, 각 컴포넌트가 마운트될 때마다 동일한 이벤트 리스너가 중복 등록되어 이벤트 발생 시 핸들러가 여러 번 호출되는 문제가 발생했습니다.

문제 해결 방법

이 문제를 해결하기 위해 window 전역 객체를 사용하여 이벤트 리스너가 한 번만 등록되도록 상태를 관리합니다.

해결전 코드

//-- main.js

import { createApp } from 'vue';
import App from './App.vue';
import mitt from 'mitt';

// mitt 인스턴스를 window 객체에 등록
window.emitter = mitt();

const app = createApp(App);
app.mount('#apptr');
//-- currencyMaster.vue
<template>
</template>

<script setup>
import { onMounted, onBeforeUnmount } from 'vue';

onMounted(() => {
    window.emitter.on('FAReceive', handleFAReceive);
});

</script>


//-- order.vue
<template>
<currencyMaster ref="currencyMaster">
</template>
<script setup>
import { onMounted, onBeforeUnmount } from 'vue';
import currencyMaster from './currencyMaster.vue'
</script>

//-- rfOrder.vue
<template>
<currencyMaster ref="currencyMaster">
</template>
<script setup>
import { onMounted, onBeforeUnmount } from 'vue';
import currencyMaster from './currencyMaster.vue'
</script>

//-- marketWatch_spot.vue
<template>
<currencyMaster ref="currencyMaster">
</template>
<script setup>
import { onMounted, onBeforeUnmount } from 'vue';
import currencyMaster from './currencyMaster.vue'
</script>

//-- marketWatch_exchange.vue
<template>
<currencyMaster ref="currencyMaster">
</template>
<script setup>
import { onMounted, onBeforeUnmount } from 'vue';
import currencyMaster from './currencyMaster.vue'
</script>

 

해결방법

1. mitt 이벤트 버스 설정

먼저, mitt를 사용하여 전역 이벤트 버스를 설정합니다. 이를 위해 main.js 파일에서 mitt 인스턴스를 window 객체에 등록합니다.

window 전역변수를 이용하여 이벤트가 등록되었는지 확인합니다.

//-- main.js

import { createApp } from 'vue';
import App from './App.vue';
import mitt from 'mitt';

// mitt 인스턴스를 window 객체에 등록
window.emitter = mitt();

const app = createApp(App);
app.mount('#apptr');

2. 이벤트 리스너 상태 관리

currencyMaster.vue 컴포넌트에서 전역 변수를 사용하여 이벤트 리스너가 이미 등록되었는지 확인하고, 한 번만 등록되도록 구현합니다.

//-- currencyMaster.vue
<template>
  <div>
  </div>
</template>

<script setup>
import { onMounted, onBeforeUnmount } from 'vue';

// 전역 변수를 사용하여 리스너 등록 상태를 추적
if (!window.isFAReceiveListenerRegistered) {
  window.isFAReceiveListenerRegistered = false;
}

const handleFAReceive = (data) => {
  console.log('FAReceive event received:', data);
};

onMounted(() => {
  if (!window.isFAReceiveListenerRegistered) {
    window.emitter.on('FAReceive', handleFAReceive);
    window.isFAReceiveListenerRegistered = true;
  }
});

</script>

이 코드는 window.isFAReceiveListenerRegistered 변수를 사용하여 이벤트 리스너가 이미 등록되었는지 확인합니다. 등록되지 않았다면, 이벤트 리스너를 등록하고 변수를 true로 설정합니다.

위와 같이 하면 emitter 겍체의 FAReceive 이벤트 array 는 1개값만 나오며 1개의 이벤트만 받습니다.