Event Bus

devjune·2021년 7월 6일
0

Vue.js

목록 보기
21/36

이전 포스팅에서 상위 컴포넌트와 하위 컴포넌트 간의 데이터 통신에 대해 다룬적이 있다.
this.$emit과 props다.

이건 상위,하위 컴포넌트 간의 데이터 통신인데, 상 하위 관계가 아닌 완전히 다른 컴포넌트 간의 데이터 통신은 어떻게 할까?

이번 포스팅 주제인 Event Bus에 대해 알아보자.

// utils/bus.js
import Vue from 'vue';

export default new Vue();

우선 이벤트를 받고 전달하는 용도로 bus.js 파일을 생성한다.
Vue객체 내 $emit과 $on을 사용하기 위함이다.

이벤트 전달을 위해 $emit을 이용하여 이벤트를 생성하고,
이벤트를 받기 위해 $on을 이용하여 이벤트 구독을 한다.

// A.vue
<template>
   <div>
      <button @click="sendEvent">send</button>
   </div>
</template>

<script>
import bus from '../utils/bus.js';

export default {
   methods: {
      sendEvent() {
      	bus.$emit('send', 1);
      }
   }
}
</script>

// B.vue
<template>
   <div>
      {{ receivedData }}
   </div>
</template>

<script>
import bus from '../utils/bus.js';

export default {
   data() {
      return {
         receivedData: ''
      }
   },
   methods: {
      receiveEvent() {
      	bus.$emit('send', data => {
           this.receivedData = data;
        });
      }
   }
}
</script>

이 원리를 이용하여 로딩 스피너를 구현할 수 있다.

// NewsView.vue
<template>
  <div>
    <list-item />
  </div>
</template>

<script>
import ListItem from '../components/ListItem.vue';
import bus from '../utils/bus.js';

export default {
  components: {
    ListItem
  },
  created() {
    bus.$emit('start:spinner');
    setTimeout(() => {
      this.$store.dispatch('FETCH_NEWS')
        .then(() => {
          console.log('fetched');
          bus.$emit('end:spinner');
        })
        .catch(err => {
          console.log(err);
        });
      bus.$emit('end:spinner');
    }, 3000);
  }
};
</script>
// App.vue
<template>
  <div id="app">
    <tool-bar />
    <main>
      <transition :name="transitionName">
        <router-view></router-view>
      </transition>
    </main>
    <spinner :loading="loadingStatus"/>
  </div>
</template>

<script>
import ToolBar from './components/ToolBar.vue';
import Spinner from './components/Spinner.vue';
import bus from './utils/bus.js';

export default {
  components: {
    ToolBar,
    Spinner
  },
  data() {
    return {
      transitionName: "",
      loadingStatus: false
    };
  },
  methods: {
    startSpinner() {
      this.loadingStatus = true;
    },
    endSpinner() {
      this.loadingStatus = false;
    }
  },
  created() {
    bus.$on('start:spinner', this.startSpinner);
    bus.$on('end:spinner', this.endSpinner);
  },
  beforeDestroy() {
    bus.$off('start:spinner', this.startSpinner);
    bus.$off('end:spinner', this.endSpinner);
  }
}
</script>
  1. App.vue에서 로딩 스피너를 구현한다.
  2. NewsView.vue에서 created() 훅이 시작될 때 bus.$emit('start:spinner'); 을 이용하여 start:spinner이벤트를 발생시킨다.
  3. App.vue에서 bus.$on('start:spinner', this.startSpinner); 을 이용하여 생성된 이벤트를 구독하고 startSpinner 메소드를 실행시킨다.
  4. component가 소멸되기 전 bus.$off('start:spinner', this.startSpinner);를 이용하여 생성된 이벤트를 삭제 시킨다.

출처 : Vue.js 완벽 가이드 - 실습과 리팩토링으로 배우는 실전 개념

profile
개발자준

0개의 댓글