ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [VueJS] 컴포넌트간 통신을 위한 이벤트 버스 개념과 활용
    frontend/vue&nuxt 2022. 9. 5. 14:21

    오늘은 Vue 개발할 때 자주 사용되는 것 중 하나인 컴포넌트 간 통신을 위한 이벤트버스(EventBus)에 대해서 알아보도록 하겠습니다. 보통 컴포넌트간의 통신을 위해서는 refs를 이용하여 상위컴포넌트에서 하위컴포넌트를 호출하거나 내장 이벤트버스(this.$emit)를 이용하여 하위컴포넌트에서 상위컴포넌트를 호출합니다.

     

    개발을 진행하다보면 상위 또는 하위로 드릴링하여 들어가여 호출하고 받는 것이 아니라 직접적으로 컴포넌트의 이벤트를 실행하고 싶은 경우가 있습니다. 이럴 경우 우리는 EventBus라는 것을 사용하게 됩니다. 자세한 내부 코드가 궁금하면 vue 공식 github 링크에 들어가셔서 확인하실 수 있습니다. github 코어 코드를 보다보면 배우는게 많으니 시간날때 core부터 찬찬히 보면 좋다고 생각합니다. API 통신 및 페이지 전환 시 로딩화면을 넣는 것을 예시로 하여 설명드리겠습니다.

     

    1. utils/EventBus.js

    import Vue from 'vue'
    export default new Vue();

    이벤트 버스를 통신에 사용하기 위하여 Vue를 생성하여 반환하여 줍니다.

     

    2. components/core/Loading.vue

    <template>
        <div v-if="loadingList.length > 0" class="loading-outer">
            <div class="loading-inner">
                <div class="loading-spinner"></div>
            </div>
        </div>
    </template>
      
    <script>
    import EventBus from '@/utils/EventBus'
    
    export default {
        data: () => ({
          loadingList : []
        }),
        created() {
            let self = this;
            EventBus.$on("loading:show", self.show);
            EventBus.$on("loading:hide", self.hide);
        },
        methods: {
            show(optsParams) {},
            hide() {}
        }
    }
    </script>
    
    <style scoped>
    .loading-outer {}
    .loading-inner {}
    .loading-spinner {}
    
    @keyframes spin {
        from {
            transform: rotate(0deg);
        }
        to {
            transform: rotate(360deg);
        }
    }
    </style>

    해당 컴포넌트를 설명하면 로딩화면을 제어할 data와 method를 셋팅하여 주었고, 이를 다른곳에서도 사용할 수 있게 컴포넌트 created시점에 EventBus.$on을 이용하여 호출명과 실제 함수를 연결하여 주었습니다. 이제 이를 최상위 컴포넌트인 App.vue에 추가하면 전역에서 사용할 수 있게 될 것입니다. 메소드 내부동작 및 CSS 코드는 따로 댓글 달아주시면 소스 보내드리겠습니다. 글이 너무 길어져서 내용부분을 비우고 올리게 되었습니다.

     

    3. utils/Loader.js

    import EventBus from "@/utils/EventBus";
    
    export default {
        show(opts) {
            EventBus.$emit('loading:show', opts);
        },
        hide() {
            EventBus.$emit('loading:hide')
        }
    }

    컴포넌트 created시점에 $on을 통하여 이벤트를 등록하였다면 다른곳에서 스크립트를 이용해서 로딩화면을 호출 할 수 있게 $emit을 이용하여 함수를 만들어 줍니다. $emit('호출명')을 하여 show, hide를 연결하여 줍니다.

     

    4. App.vue

    <template>
      <div id="app">
        <router-view />
        <Loading></Loading>
      </div>
    </template>
    
    <script>
    import Loading from '@/components/core/Loading.vue';
    export default {
      components: { Loading }
    }
    </script>

    로딩화면은 취상위 컴포넌트에 추가되어야 하기 때문에 App.vue에 Loading 컴포넌트를 추가하여 줍니다.

     

    5. views/Test.vue

    <template>
      <div>
        <button @click="loading">로딩화면 ON</button>
      </div>
    </template>
    
    <script>
    import Loader from '@/utils/Loader';
    
    export default {
      methods: {
        loading() {
          Loader.show();
        }
      },
    }
    </script>

    그 후 테스트할 화면에서 Loader.js를 import하여 Loader.show를 하여주면 메소드 내의 EventBus.$emit 을 통해 호출하고, Loading.vue가 전역에 등록된 후 created시점에 등록되었던 show함수가 실행되어 화면에 로딩화면이 동작하게 됩니다.

     

    이렇게 이벤트 버스를 통하여 컴포넌트의 특정 동작을 활용할 수 있습니다. dim처리가 되어있는 로딩화면 혹은 메세지 컴포넌트등을 호출하거나 할 때 유용하게 사용할 수 있습니다. 하지만 프로젝트 규모가 커지고 호출하는 포인트 들이 늘어난다면 관리가 어려워지니 꼭 필요한 곳에만 사용하는 것이 좋다고 생각합니다. 간단한 로딩화면 호출에 대한 예제와 함께 진행해본 EventBus의 활용입니다. 많은 도움이 되셨으면 좋겠습니다.

    반응형

    댓글

Designed by Tistory.