2024년 8월 30일 금요일

Vuetify3 와 vue3를 활용해서 dynamic confirm 컨퍼런트 생성하기.

Vuetify3 와 vue3를 활용해서 dynamic confirm 컨퍼런트 생성하기.

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로딩 없이 함수형태로 사용할수 있게 되었습니다.

댓글 없음:

댓글 쓰기