728x90
반응형
- 개요
- 흐름
- 구현
- 실행
개요
Vue.js 에서는 Vuex와 같은 상태관리 라이브러리를 활용하지 않는다면, 컴포넌트 계층간 데이터를 주고받는 대표적인 방법은 부모 컴포넌트와 자식 컴포넌트 간의 Props와 Emit 으로의 데이터 통신이다.
부모, 자식간에만 데이터 교환이 아닌 서로 관계가 독립적이거나 형제관계인 컴포넌트간 데이터를 주고받는 방법은 2.0에서는 $emit과 $on을 활용해서 데이터 교환을 하는 EventBus가 존재한다.
- 데이터를 보낼 발신자 컴포넌트 측에서 $emit을 활용해 보낼 event명과 데이터를 보낸다.
- 데이터를 받을 수신자 컴포넌트 측에서 $on을 활용해 받은 데이터를 어떻게 처리할지 작성한다.
다음과 같은 순서로 EventBus는 동작한다. 그런데, 수신자 컴포넌트에서 비동기적으로 어떤 로직을 수행한 후 다시 발신자에게 보내 해당 값을 받아 발신자 컴포넌트에서 로직을 수행해야 할 경우가 있다.
나와같은 경우는 dialog라고 하는 Vuetify에서 제공되는 Component 즉, 브라우저에서 Alert 나 Confirm 창을 대신하는 팝업 컴포넌트를 수신자 컴포넌트로 사용해 확인 / 거절과 같은 버튼이벤트가 수행될때 비동기적으로 확인/거절 값을 발신자 컴포넌트에서 받아야했다.
하여 Nuxt.js & Vue.js 에서 비동기 활용 EventBus Emit후 CallBack 받아 사용했고 이를 남긴다.
흐름
- 발신자 컴포넌트의 $emit 함수를 Promise로 감싼후 emit의 데이터에 resolve와 reject 함수를 포함시켜 보내준다.
- 수신자 컴포넌트의 $on 함수에서 resolve와 reject함수를 받아 원하는 이벤트가 발생했을때 callback 함수들을 호출한다.
- 발신자 컴포넌트에서 호출된 값을 받아 원하는 로직을 수행한다.
구현
참고사항
- Nuxt.js 프레임워크와 Typescript 가 사용되었다.
- vue.js 버전은 2.0이다.
- Class-base-components로 작성되었다.
발신자 Component
......
enum dialogStatus {
alert = 'alert',
confirm = 'confirm',
}
//흐름 3.부분
async confirm() {
const result = await this.onDialog(dialogStatus.confirm, '원하는 메세지')
console.info(result)
}
//흐름 1.부분
async onDialog(status: dialogStatus, message: string) : Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
this.$nuxt.$emit(status, message, resolve, reject)
})
}
.....
수신자 Component
...
<v-card-actions>
<v-spacer></v-spacer>
<v-btn @click="isConfirm(true)"> 확인 </v-btn>
<v-btn v-if="status == 'confirm'" text @click="isConfirm(false)"> 취소 </v-btn>
</v-card-actions>
...
...
dialog = false as boolean
content = null as string
status = null as string
confirmVal = null as boolean
tempResolve = null as Function
/*
* 발신 데이터를 받아 어떻게 할지 미리 작성하기 위해 created훅에 작성했다.
*/
created() {
const v = this
this.$nuxt.$on('alert', busData => {
v.status = 'alert'
this.openDialog()
v.content = busData
})
this.$nuxt.$on('confirm', (busData, resolve, reject) => {
v.status = 'confirm'
this.openDialog()
v.content = busData
//promise의 resolve함수를 이벤트가 발생할때 실행시키기 위해 변수에 담는다.
//흐름 2.부분
v.tempResolve = resolve
})
}
isConfirm(confirmVal : boolean) {
this.dialog = false
if (this.status === 'confirm') {
//변수에 담은 resolve함수를 v-btn태그의 @click이벤트에 걸어준 isConfirm함수가
//실행될때 실행시킨다.
// 흐름2. 부분
this.tempResolve(confirmVal)
}
}
...
실행
728x90