boolean
값의 로딩 데이터를 선언하고 props
로 로딩데이터를 로딩 애니메이션이 있는 컴포넌트에 넘겨주어 표현하는 방법도 있지만,
React와 다르게 Vue에서는 emit
으로 이벤트를 전달해 함수를 동작시키는 방법도 존재한다.
하지만 여러 곳에서 로딩 컴포넌트가 사용되기 때문에, 단순히 emit
을 사용하기에는 관리 포인트가 늘어나고 복잡해지는 단점을 겪을 수 있다.
따라서 App.vue에서 데이터를 선언한 후, event-bus
라는 것을 활용하여 여러곳의 하위 컴포넌트에서 emit
으로 로딩 컴포넌트를 동작시기는 방식으로 구현해보았다.
bus.js라는 파일을 다음과 같은 폴더를 생성 후 만들어 줬다.
src/utils/bus.js
import Vue from "vue";
export default new Vue();
이벤트 버스 객체를 만들어 줬으니, 이것을 불러와서 사용하는 코드이다.
이곳에서 하위 컴포넌트에서 보내주는 이벤트 들을 받기위해 bus.$on
으로 받을 이벤트에 따라 동작하는 함수를 정의했다.
이곳에 등록된 함수로 loadingStatus 값을 바꾸어서, 로딩 컴포넌트를 제어할 것이다.
beforeDestroy에 꼭 등록했던 이벤트를 지워주어야 한다! React에서 useEffect로 이벤트를 등록 후, 지우는 이유와 같이 메모리 낭비를 하지 않기 위해서!
App.vue(이벤트를 받음)
<template>
<div id="app">
<SpinnerComponent :loading="loadingStatus" />
</div>
</template>
<script>
import SpinnerComponent from "@/components/SpinnerComponent.vue";
import bus from "@/utils/bus";
export default {
name: "App",
components: {
SpinnerComponent,
},
data() {
return {
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>
어떤 자식 컴포넌트.vue(이벤트를 보냄)
<template>
<div></div>
</template>
<script>
import bus from "@/utils/bus";
export default {
created() {
bus.$emit("start:spinner");
setTimeout(() => {
bus.$emit("end:spinner");
}, 3000)
},
};
</script>