Vuetify3 와 vue3를 활용해서 dynamic confirm 컨퍼런트 생성하기.
이번에 vuetify3와 vue3를 사용하는 프로젝트에서 confirm component를 개발해야해서 찾아서 개발해보던 중에 관련된 리소스가 많이 존재하지 않는것 같아, 이 내용을 공유할려고 합니다. 저는 이런 방식으로 dynamic Confirm 컨퍼런트를 개발했습니다.
개발해야하는 Component 설명
https://vuetifyjs.com/en/components/dialogs/#usage
해당 Component를 통해 유저가 액션이 발생할 경우, 한번 더 확인하는 형태의 수단으로 사용
문제점:
기본적으로 component를 사용하는 page에 import후에 이벤트를 받아서 사용해야했음.
이 경우 불필요하게 모든 페이지 내에 해당 component를 import해야하는 번거러움이 생김.
또 코드가 수정되거나 이름이 변경되었을 경우 사용하는 모든 페이지에 내용을 수정해야함
해결방법:
Dynamic Component를 사용해서 dialog를 로딩하고, 결과값을 promise를 통해 전달 받도록 작업
샘플 코드
confirm/index.js
import Confirm from './Confirm.vue';
export function confirm(options={}) {
const wrapper = document.createElement('div');
document.body.appendChild(wrapper);
return new Promise((resolve) => {
let app;
const comp = h(Confirm, {
message: message,
value: true,
onDestroy: (value) => {
resolve(value);
app?.unmount();
app = undefined;
},
});
app = createApp(comp, options.props);
app.use(vuetify);
app.mount(wrapper);
});
}
confirm/Confirm.vue
<template>
<v-dialog
:model-value="value"
:persistent="persistent"
:max-width="maxWidth"
@input="change"
>
<v-card>
<v-card-title>{{ title }}</v-card-title>
<v-card-text>{{ message }}</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn v-if="selectable" text color="red" @click="choose(false)">No</v-btn>
<v-btn text color="green" @click="choose(true)">Yes</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup>
import { ref } from 'vue';
const props = defineProps({
message: {
type: String,
default: '',
},
onDestroy: {
type: Function,
required: true,
},
});
const value = ref(true);
const change = (open) => {
if (open) {
return;
}
props.onDestroy(val);
};
const choose = (val) => {
props.onDestroy(val);
value.value = val;
};
</script>
pages/SamplePage.vue
<template>
...
</template>
<script setup>
import {confirm} from './confirm';
const userAction = async () => {
const result = await confirm({ message: "Are you Sure?" });
....
}
</script>
저의 경우는 이런식으로 코드를 구성해서 개발했습니다. vue3에서 제공하는 createApp과 h 를 통해 component 와 vuetify3 library를 use 함수를 통해 inject 시키고 그 이후에 wrapper html을 생성해서 해당 dom안에 component를 매핑하는 방식입니다.
h함수에서 onDestory 함수를 구현해서 props로 전달했고, component내에서는 액션이 발생시에 props 에 있는 onDestory를 호출하고 그 결과값을 Promise의 resolve로 호출 하는 방법입니다.
이걸 통해 samplePage에서는 별도의 confirm로딩 없이 함수형태로 사용할수 있게 되었습니다.