๐ ๋ชฉ์ฐจ
- ์๋ก
- ๊ธฐ์กด ๋ชจ๋ฌ ๊ด๋ฆฌ
- ๊ธฐ์กด ๋ชจ๋ฌ ๊ด๋ฆฌ์ ๋ฌธ์ ์
- ์ด๋ป๊ฒ ํด๊ฒฐํด์ผํ ๊น? interface ์ก์๋ณด๊ธฐ
- ์ promise๋ฅผ ์ฌ์ฉํ๋๊ฐ?
- ์ด๋ป๊ฒ ๊ตฌํ์ ํด์ผํ ๊น?
- ๊ทธ๋ผ composition์ ์ด๋ป๊ฒ ์ฌ์ฉ์ด ๋์ด์ง๊น?
- ๊ฒฐ๋ก
๐ ์๋ก
์๋
ํ์ธ์. ์๋ ์
๋๋ค. ์ค๋์ ๊ฐ์ฅ ๋ง์ ๋ถ๋ค์ด ๊ณ ๋ฏผํ์๋ ๋ชจ๋ฌ ํน์ ๋ค์ด์ผ๋ก๊ทธ ๊ด๋ฆฌ์ ๋ํด์ ํ๋ฒ ์์๋ณด๊ฒ ์ต๋๋ค.
์ค๋ ๊ณ ๋ฏผ ๋์ ๋์จ ์ ์๋ ํน์ ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์๋ค๋ฉด ๋๊ธ๋ก ๋ฌ์์ฃผ์ธ์. ๊ทธ๋ผ ์์ํ๊ฒ ์ต๋๋ค.
๐ ๊ธฐ์กด ๋ชจ๋ฌ ๊ด๋ฆฌ
์ฐ๋ฆฌ ํ๋ฒ ๋ชจ๋ฌ์ ๋์์ผํ๋ค๊ณ ์๊ฐ์ ํด๋ณผ๊น์?
๊ทธ๋ผ ์ฐ๋ฆฌ ๋จธ๋ฆฌ์์ ๊ฐ์ฅ ๋จผ์ ๋๋ ์๊ฐ์ vuex๋ฅผ ํตํ ์ค์์นญ ๊ด๋ฆฌ ์ผ๊ฑฐ์์. ๋๋ต์ ์ผ๋ก ์ด๋ ๊ฒ ๋ณดํต ๊ตฌํ์ ํ์์๊ฑฐ ๊ฐ์์.
// store.js
export default createStore({
state: {
modalOn: false
},
mutations: {
setModalOn(state) {
state.modalOn = true;
},
setModalOff(state) {
state.modalOn = false;
},
}
});
// App.vue
<template>
<div>
<h1>APP</h1>
<SimpleModal v-if="modalOn" />
<button @click="setModalOn">ModalOn</button>
</div>
</template>
<script>
import SimpleModal from './components/SimpleModal';
import { mapState, mapMutations } from 'vuex';
export default {
name: 'App',
components: {
SimpleModal
},
computed: {
...mapState(['modalOn'])
},
methods: {
...mapMutations(['setModalOn', 'setModalOff'])
}
};
</script>
๋๋ต ์ด๋ฐ ํํ๋ฅผ ์๊ฐํ๊ณ ๊ณ์ จ๋์? ์ ๋ํ ์ด๋ฐ on, off(boolean) ํํ๋ก modal์ ๊ด๋ฆฌ๋ฅผ ํ์์๋๋ฐ, ์ด๋ ๊ฒ ๊ด๋ฆฌ๋ฅผ ํ์์๋ ์๊ธฐ๋ ๋ฌธ์ ์ ์ ํ๋ฒ ์ง์ด๋ณด๊ฒ ์ต๋๋ค.
๐ ๊ธฐ์กด ๋ชจ๋ฌ ๊ด๋ฆฌ์ ๋ฌธ์ ์
1. ๋ง์ฝ์ ๊ด๋ฆฌ๋ฅผ ํด์ผํ ๋ชจ๋ฌ์ด ๋ง์ ์ง๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น?
๋ง์ฝ์ vuex๊ฐ ๋ง์ ์ง๋ค๊ณ ๊ฐ์ ์ ํด๋ณผ๊ฒ์. ๊ทธ๋ผ ์๋ง ์ฌ๋ฌ๋ถ์ store๋ ์ด๋ฐ ํํ๊ฐ ๋ ๊ฑฐ ๊ฐ์์.
export default createStore({
state: {
modalOn1: false,
modalOn2: false,
modalOn3: false,
modalOn4: false,
modalOn5: false,
modalOn6: false,
//... ๐ฅ ๋ฌด์ํ ๋ง์ ๋ชจ๋ฌ๋ค์ ๊ด๋ฆฌํ๋ ์ํ๊ฐ ํ์ํจ
},
mutations: {
setModalOn1(state, payload) {
state.modalOn = payload;
},
setModalOn2(state, payload) {
state.modalOn = payload;
},
// ... ๐ฅ ๋ฌด์ํ ๋ง์ ๋ชจ๋ฌ๋ค์ ๊ด๋ฆฌํ๋ ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ์ํ ์ฝ๋๋ค์ด ์์ฑ๋์ด์ผ ํจ.
}
});
๊ณผ์ฐ ์ ๋ง ์ด๋ ๊ฒ ๊ด๋ฆฌํ๋ ๊ฒ์ด ๋ฐ๋์งํ ๋ฐฉ๋ฒ์ผ๊น์?
ํน์ ์ง๋์น๊ฒ vuex๋ฅผ ์์กดํ๊ณ ์๋ค๋ ์๊ฐ์ด ๋์๋์?
์๋ก์ด ๋ชจ๋ฌ์ ์ถ๊ฐํ ๋ ๋ง๋ค vuex๋ฅผ ๊ฑด๋ค์ฌ์ผํ๋ ์ํฉ์ด ๋ฐ์ํ ๊ฑฐ๊ณ ๊ทธ๋ก ์ธํด vuex๋ ์ ์ ๋น๋ํด์ ธ๊ฐ ๊ฒ๋๋ค.
๊ทธ๋ผ ํด๋น vuex๋ ๊ณผ์ฐ ๊ด๋ฆฌ๊ฐ ๋ ๊น์?
๋ง์ฐฌ๊ฐ์ง๋ก App.vue๋ ๊ฐ์ด ๋์ด๋๊ฒ ๋ ํ
๋ฐ ๊ด๋ฆฌ ํฌ์ธํธ๊ฐ ๋๋๊ฑด ์๋๊น์?
2. vuex์ mutations๋ง ๋ณด๊ณ ์ค์ ๋ก ์ด๋ค ๋ชจ๋ฌ์ด ๋ฐ์ด์ง๋์ง ํ๋ฒ์ ํ์ ์ด ๊ฐ๋ฅํ๊ฐ?
์์ ์ฝ๋๋ฅผ ๋ค์ ํ๋ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
// App.vue
<template>
<div>
<h1>APP</h1>
<SimpleModal v-if="modalOn" />
<button @click="setModalOn">ModalOn</button>
</div>
</template>
<script>
import SimpleModal from './components/SimpleModal';
import { mapState, mapMutations } from 'vuex';
export default {
name: 'App',
components: {
SimpleModal
},
computed: {
...mapState(['modalOn'])
},
methods: {
...mapMutations(['setModalOn', 'setModalOff'])
}
};
</script>
ํด๋น ์ฝ๋์์๋ depth๊ฐ ํ ๋จ๊ณ์ด๊ธฐ ๋๋ฌธ์ setModalOn์ ํ๋ค๋ฉด ๋๋ต์ ์ผ๋ก ์ด๋ค ๋ชจ๋ฌ์ด ์ด๋ฆฌ๋์ง ์ ์ ์์๊ฑฐ ๊ฐ์์.
๊ทผ๋ฐ ๋ณดํต ์ฐ๋ฆฌ๊ฐ ์ฐ๋ ์ฝ๋๋ ์์ฒญ ๋๊ฒ ๋ง์ component์ depth๋ฅผ ๋ค์ด๊ฐ์ผ ํฉ๋๋ค. ๋ง์ฝ์ ๊ทธ๋ผ depth๊ฐ ๊น์ ๋ ์ด๋ป๊ฒ ์ด๋ค ๋ชจ๋ฌ์ด ์ด๋ฆฌ๋์ง ํ์
์ ํ ๊น์?
- ChildComponent์์ ์ด๋ค Mutation์ ์ฌ์ฉํ๋์ง ํ์ธํ๋ค.
- Vuex์ ๋ค์ด๊ฐ์ ์ฐพ์ Mutation์ด ์ด๋ค ์ํ๋ฅผ ๋ฐ๊ฟ์ฃผ๋์ง ํ์ ํ๋ค.
- App.vue๋ฅผ ํ์ธํ๋ค.(ํน์ ModalContainer๋ก ๋ชจ์๋๋ค๋ฉด ํด๋น Container๋ฅผ ํ์ธํ๋ค.)
- ๊ทธ์ ์์ผ ์ด๋ค ๋ชจ๋ฌ ์ปดํฌ๋ํธ๊ฐ ์ด๋ฆฌ๋์ง ํ์ธํ ์ ์๋ค.
๋ชจ๋ฌ์ ์ฌ๋ method ํ์ค์ ์ฝ์์ ๋ ์ด๋ค ๊ธฐ๋ฅ ๋์์ ํ๋์ง ์ด๋ค ์ปดํฌ๋ํธ๊ฐ ์ด๋ฆฌ๋์ง ์ ์๋ง ์๋ค๋ฉด ์ ๋ง ์ข์ง ์์๊น์?
3. ๋ง์ฝ์ ๋์์ ๊ฐ์ ๋ชจ๋ฌ์ ๋์์ผ ํ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น?
์์ ๊ฐ์ด ๊ด๋ฆฌ๋ฅผ ํ๊ฒ ๋๋ค๋ฉด ๊ฐ์ ๋ชจ๋ฌ์ด์ง๋ง ์๋ก์ด ๋ชจ๋ฌ์ ๋ฑ๋ก์ ํ๋ ๋ฐฉ์์ผ๋ก ๋ฑ๋ก์ ํด์ผ ํ ๊ฑฐ ๊ฐ์์. ๊ทธ๋ผ ๋๊ฐ์ด vuex์ App.vue๊ฐ ๋ง์ด ๋์ด๋๊ฒ ๋ ๊ฑฐ ์์. ์ ๋ง ์ด๊ฒ ์ข์ ๋ฐฉ๋ฒ์ผ๊น์?
4. ๋ง์ฝ์ ๋ชจ๋ฌ์์ ์ด๋ค ๊ฐ์ ๋ฐ์์ ํ์ด์ง์์ ์ฒ๋ฆฌ๋ฅผ ํด์ผํ๋ค๋ฉด?
๋ชจ๋ฌ๊ณผ ์ผ๋ฐ ์ปดํฌ๋ํธ๊ฐ ์๋ก ์ํต์ ํด์ผํ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น์? ๋ง์ฐฌ๊ฐ์ง๋ก vuex๋ฅผ ๊ฐ์ฅ ๋จผ์ ๋ ์ฌ๋ฆฌ์ค๊ฑฐ ๊ฐ์์. ๊ทธ๋ผ vuex์ ๋๋์ฑ ์์กด์ ์ด๊ฒ ๋์ง ์์๊น์?
๐ง ๋ฌธ์ ์ ๋ชจ์๋ณด๊ธฐ
- vuex์ ์ง๋์น๊ฒ ์์กด์ ์ด๊ฒ ๋๋ค.
- App.vue ํน์ ModalContainer๊ฐ ์ปค์ง๊ฒ ๋์ด ๊ด๋ฆฌ ํฌ์ธํธ๊ฐ ๋์ด๋๊ฒ ๋๋ค. (vuex ๋ํ ๋ง์ฐฌ๊ฐ์ง)
- ์ด๋ค ๋ชจ๋ฌ์ด ์ด๋ฆฌ๋์ง ์ ํํ๊ฒ ์ฐพ์๋ณด๊ธฐ๊ฐ ํ๋ค๋ค.
- ๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ์ด๋ ค๊ณ ํ๋ค๋ฉด ์๋ก์ด ์ปดํฌ๋ํธ ๋ฑ๋ก ๋ฐฉ์๊ณผ ๋์ผํ ์ฌ์ดํด์ ๊ฐ์ ธ์ผ ํ๋ค.
๐ ์ด๋ป๊ฒ ํด๊ฒฐ ํด์ผํ ๊น? interface ์ก์๋ณด๊ธฐ
๊ฒฐ๊ณผ์ ์ผ๋ก ์ต์ข ์ฌ์ฉ๋ฒ์ ์ด๋ฐ ํํ๊ฐ ๋ ๊ฑฐ ๊ฐ์์.
vue3 setup
<script setup>
import { useModal } from 'vue3-use-modal';
import SimpleModal from 'components/SimpleModal.vue';
const modal = useModal();
const onClick = async () => {
const name = await modal.addModal<string>(
'SimpleModal',
SimpleModal,
{ props: { name: 'eddie' } }
});
alert(`My name is: ${name}`);
}
</script>
vue3 ์ผ๋ฐ ๋ฌธ๋ฒ
<script lang="ts">
import SimpleModal from 'components/SimpleModal.vue';
export default {
methods: {
async onClick() {
const name = await this.$modal.addModal<string>(
'SimpleModal',
SimpleModal,
{ props: { name: 'eddie' } }
});
alert(`My name is: ${name}`);
}
},
}
</script>
์ด๋ ๊ฒ ์ฌ์ฉ์ด ๋์ด์ง๋ค๋ฉด ์์ ๋ฌธ์ ์ ์ ํด๊ฒฐํ ์ ์์๊น์?
- vuex์ ์ง๋์น๊ฒ ์์กด์ ์ด๊ฒ ๋๋ค.
-> vuex๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค.
2. App.vue ํน์ ModalContainer๊ฐ ์ปค์ง๊ฒ ๋์ด ๊ด๋ฆฌ ํฌ์ธํธ๊ฐ ๋์ด๋๊ฒ ๋๋ค. (vuex ๋ํ ๋ง์ฐฌ๊ฐ์ง)
-> App.vue๋ ModalContainer์ ๋ช
์์ ์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ถ์ฌ์ฃผ๋ ํํ๊ฐ ์๋๋ผ ๋์ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๊ด๋ฆฌ ํฌ์ธํธ๋ ์ฌ์ฉํ๋ ์ชฝ์์๋ง ๊ด๋ฆฌ๋์ด ์ง๋ค.
3. ์ด๋ค ๋ชจ๋ฌ์ด ์ด๋ฆฌ๋์ง ์ ํํ๊ฒ ์ฐพ์๋ณด๊ธฐ๊ฐ ํ๋ค๋ค.
-> ํด๋น ํจ์๋ง ๋ณด๊ณ ์ด๋ค ์ปดํฌ๋ํธ๊ฐ ์ด๋ฆฌ๋์ง ๋ฐ๋ก ๋ณผ ์ ์๋ค.
4. ๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ์ด๋ ค๊ณ ํ๋ค๋ฉด ์๋ก์ด ์ปดํฌ๋ํธ ๋ฑ๋ก ๋ฐฉ์๊ณผ ๋์ผํ ์ฌ์ดํด์ ๊ฐ์ ธ์ผ ํ๋ค.
-> key๊ฐ์ผ๋ก ์์ ์์ฌ๋ก ๋์์ ์์ ํ ์ ์๋ค.
๐ ์ promise๋ฅผ ์ฌ์ฉํ๋๊ฐ?
Q> ์๋ ์ ํํ promise๋ฅผ ์ฌ์ฉํ์ด์?
์ฝ๋๋ฅผ ์ค๊ฐ์ ์ ์ ๋ฉ์ถ๋ promise์ ํน์ฑ๊ณผ promise์ ๊ณ ์ ์ ํน์ฑ์ ์ฌ์ฉํ๊ณ ์ถ์ด์ ์
๋๋ค.
ํนํ reject๋ฅผ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์๊ฑฐ๋ผ๊ณ ํ๋จ์ ํ์ด์.
reject๋ ์ค๊ฐ์ ์ฝ๋ ์คํ์ ๊ฐ์ ์ ์ผ๋ก ๋ฉ์ถ๊ณ ๋์๊ฐ๋ ํน์ฑ์ด ์์ด์.
์๋ฅผ ๋ค์ด ์ด๋ฐ ์ฝ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํด๋ณผ๊ฒ์.
const onClick = async () => {
const myname: string = await hello<string>();
console.log(myname)
}
hello(Promise)๋ฅผ ๋ฐํํ๊ฒ ๋๋๋ฐ ํน์ ์ํฉ์ผ๋ reject๋ฅผ ๋ฐ์์ํจ๋ค๊ณ ๊ฐ์ ์ ํ๋ค๋ฉด ๊ทธ๋ฆฌ๊ณ console.log๋ฅผ ์ฐ์ผ๋ฉด ์๋๋ ์ํฉ์ด๋ผ๋ฉด reject๊ฐ ๊ฐ์ฅ ์ ํฉํ๋ค๊ณ ์๊ฐํ์ด์.
์ข ๋ ์ค๋ฌด์ ์ธ ์์๋ฅผ ๋ค์ด๋ณผ๊ฒ์. ๋ง์ฝ ์น๊ฐ์ด ํ์๋น๋ฅผ ์ง๋ถํ๋ค๋ฉด ์น๊ฐ๊ณผ ๊ธฐ์ฌ๋์๊ฒ notification์ ๋ณด๋ด์ผํ๊ณ ์ง๋ถ์ ํ์ง ์์๋ค๋ฉด notification์ ๋ณด๋ด๋ฉด ์๋๋ค๊ณ ํด๋ณด๊ฒ ์ต๋๋ค. ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์์.
const onClick = async () => {
await payKakaoTexi(); // ์น๊ฐ์ด ๊ธ์ก์ ์ง๋ถํ๋ฉด resolve ๊ทธ๋ ์ง ์๋ค๋ฉด reject
sendNotifictationToClient();
sendNotificationToDriver();
}
๐ ์ด๋ป๊ฒ ๊ตฌํ์ ํด์ผํ ๊น?
๐ง ํด๋น ๊ตฌํ ๋ฐฉ๋ฒ์ vue3 ๊ธฐ๋ฐ์ผ๋ก ์์ฑ์ด ๋์์ต๋๋ค.
vue3์์์ createApp์ ์ฌ์ฉํ๊ณ ์ด๊ฒ์ plugin ํํ๋ก ๊ด๋ฆฌ๋ฅผ ํ ์์ ์ ๋๋ค. ๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ ์์ด๋ค์ด ํ์ํด์.
- ModalContainer (์๋ก์ด root app)
- ๋์ app๊ณผ ์๋ก์ด root app(modalContainer)๋ฅผ ์ฐ๊ฒฐํด ์ค ์ ์๋ ํ๋ฌ๊ทธ์ธ
- ModalContainer์ ํจ์๋ค์ ์ ์ญ์์ ์ฌ์ฉํ ์ ์๋ ํ๋ฌ๊ทธ์ธ
ModalContainer ๋ง๋ค๊ธฐ
๋จผ์ Modal์ ๋ด์ ์ ์๋ ModalContainer๋ฅผ ์์ฑํด์ค๋๋ค. ์ ์ฒด์ ์ธ ์ฝ๋๋ฅผ ๋จผ์ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค.
<template>
<div>
<component
v-for="modal in modals"
:key="modal.key"
:is="modal.component"
v-bind="modal.props"
@resolve="(value) => onResolve(value, modal.key, modal.resolve)"
@reject="(value) => onReject(value, modal.key, modal.reject)"
@close="() => closeModal(modal.key)"
/>
</div>
</template>
<script>
import { markRaw } from 'vue';
export default {
name: 'ModalContainer',
data: () => ({
modals: []
}),
methods: {
addModal(key, component, configs) {
const props = configs?.props ?? {};
this.closeModal(key);
return new Promise((resolve, reject) => {
this.modals.push({
key,
component: markRaw(component),
props,
resolve,
reject
});
});
},
closeModal(key) {
this.modals = this.modals.filter(modalInfo => {
if (modalInfo.key === key) {
modalInfo.reject();
return false;
} else {
return true;
}
});
},
onResolve(value, key, resolve) {
resolve(value);
this.closeModal(key);
},
onReject(value, key, reject) {
reject(value);
this.closeModal(key);
}
}
};
</script>
์ด์ ํ๋ํ๋์ฉ ์ดํด ๋ณผ๊น์? ๋จผ์ template ๋ถ๋ถ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
// Modals ์ ํ์
// interface Modal {
// key: string;
// component: Vue.Component;
// resolve: Promise.resolve
// reject: Promise.reject
// props: unknown
// }
<template>
<div>
<component
v-for="modal in modals"
:key="modal.key"
:is="modal.component"
v-bind="modal.props"
@resolve="(value) => onResolve(value, modal.key, modal.resolve)"
@reject="(value) => onReject(value, modal.key, modal.reject)"
@close="() => closeModal(modal.key)"
/>
</div>
</template>
๋์น๋ฅผ ์ฑ์
จ๋ค ์ถ์ด @resolve, @reject, @close๋ฅผ ๊ฐ๊ฐ์ ๋ชจ๋ฌ์์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๋ ํํ๊ฐ ๋ฉ๋๋ค.
๊ทธ๋์ ์ฌ์ฉ์ ํ๋ ์ชฝ์์ resolve, reject, close๋ฅผ emit์ผ๋ก ๊ฐ๊ฐ์ ์ํฉ์ ์ค์ ํ ์ ์์ด์.
๋ง์ฝ์ ์ด๋ค ๋ชจ๋ฌ์์ ์
๋ ฅ ๊ฐ์ ๋ฐ๊ณ ๊ทธ ์
๋ ฅ ๊ฐ์ ์ด๋ค ์ปดํฌ๋ํธ์ ์ ๋ฌ์ ํด์ผํ๋ค๊ณ ๊ฐ์ ํด๋ณธ๋ค๋ฉด ์ด๋ ๊ฒ ๋ชจ๋ฌ ์ฝ๋๋ ์ด๋ ๊ฒ ์์ฑ์ด ๋ ๊ฑฐ์์.
<template>
<div>
<input v-model="myInput" />
<button @click="$emit('resolve', myInput)">Submit</button
</div>
</template>
๊ทธ๋ฆฌ๊ณ ์ด์ script ๋ถ๋ถ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
import { markRaw } from 'vue';
export default {
name: 'ModalContainer',
data: () => ({
// Modals ์ ํ์
// interface Modal {
// key: string;
// component: Vue.Component;
// resolve: Promise.resolve
// reject: Promise.reject
// props: unknown
// }
modals: []
}),
methods: {
// ๊ฐ ์ฝ๋๋ฅผ modals์ ๋ฃ์ด์ฃผ๊ฒ ๋ฉ๋๋ค. ์ด๋ Promise๋ฅผ ์ฌ์ฉํด์ ๋๊ธฐ ์ํ๋ก ๋ง๋ค์ด์ฃผ๊ฒ ๋ฉ๋๋ค.
// ๋๊ธฐ ์ํ๊ฐ ํ๋ฆฌ๋๊ฑด ๊ฐ ๋ชจ๋ฌ์์ ๊ฒฐ์ ํ๊ฒ ๋ฉ๋๋ค. ($emit)
addModal(key, component, configs) {
const props = configs?.props ?? {};
this.closeModal(key);
return new Promise((resolve, reject) => {
this.modals.push({
key,
// markRaw ๋ฅผ ์ฌ์ฉํด์ค ์ด์ ๋ ๊ทธ๋ฅ component๋ฅผ ๋์ง๊ฒ ๋๋ฉด ์ฑ๋ฅ ์ด์๊ฐ ์์ด์ raw ํ component๋ก ๋ณ๊ฒฝ ํด์ฃผ์์ต๋๋ค.
component: markRaw(component),
props,
resolve,
reject
});
});
},
// ํด๋น ๋ชจ๋ฌ์ ๋ซ์ ์ฃผ๊ฒ๋ฉ๋๋ค.
closeModal(key) {
this.modals = this.modals.filter(modalInfo => {
if (modalInfo.key === key) {
// ์ฌ๊ธฐ์๋ reject๋ฅผ ์ฌ์ฉํ๊ฒ ๋์์ด์. resolve๋ก ๋ณ๊ฒฝํ์
๋ ๋ฌด๋ฐฉํฉ๋๋ค.
// reject๋ก ์ฌ์ฉ์ ํ๋ ์ด์ ๋ ์์ Promise ๋ถ๋ถ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก
// ๋ซ๊ฒ ๋๋ฉด Promise ๋ก ๋๊ธฐ ๋์ด์ก๋ ์ฝ๋ ์๋์ ์ฝ๋๊ฐ ์คํ์ด ๋๋๊ฑธ ๋ฐฉ์งํ๊ธฐ ์ํจ์
๋๋ค.
modalInfo.reject();
return false;
} else {
return true;
}
});
},
onResolve(value, key, resolve) {
resolve(value);
this.closeModal(key);
},
onReject(value, key, reject) {
reject(value);
this.closeModal(key);
}
}
};
ModalPlugin ๋ง๋ค๊ธฐ
๊ทธ๋ผ ์ด์ ํ๋ฒ ์ค์ ๋ก ์ฐ๊ฒฐ์ ํด๋ณผ๊น์?
import { createApp } from 'vue';
import ModalContainer from '@/modal/ModalContainer';
const createModalEl = () => {
if (!document) throw new Error('Cannot create el in server side');
const modalEl = document.createElement('div');
modalEl.setAttribute('id', 'modal');
document.body.prepend(modalEl);
return modalEl;
};
export default {
install(app) {
const modalEl = createModalEl();
const modalContainer = createApp(ModalContainer);
const exposed = modalContainer.mount(modalEl);
app.config.globalProperties.$modal = exposed;
// app์ globalProperties๋ฅผ ๊ฐ์ ธ์์ this๋ฅผ ๋๊ธฐํ ์ํจ๋ค.
modalContainer.config.globalProperties = { ...modalContainer.config.globalProperties, ...app.config.globalProperties };
}
};
์ค์ ๋ก ์ฌ์ฉํด๋ณด๊ธฐ
๊ทธ๋ผ ์ด์ ํ๋ฒ ๋ชจ๋ฌ์ ๋์๋ณผ๊น์? ์ฝ๋๋ก ํํ์ ํด๋ณด๊ฒ ์ต๋๋ค.
<template>
<section>
<h1>Container1 normal vue</h1>
<my-button @click="onClick">click me!</my-button>
</section>
</template>
<script>
import SimpleModal from '../components/SimpleModal.vue';
import MyButton from '../components/MyButton.vue';
export default {
components: { MyButton },
methods: {
async onClick() {
const name = await this.$modal.addModal(
'SimpleModal',
SimpleModal,
{ props: { myName: 'Eddie' } },
});
alert(name);
},
},
};
</script>
๋์ํ๋ ๋ชจ์ต์ ๋๋ค.
๐ ๊ทธ๋ผ ํ ์ ์ด๋ป๊ฒ ์ฌ์ฉ์ด ๋์ด์ง๊น?
ํ ์ ์ด๋ ๊ฒ ์ ์๋ฅผ ํด์ฃผ๋ฉด ๋ฉ๋๋ค.
import { getCurrentInstance } from 'vue';
// getCurrentInstance๋ก ํ์ฌ ๋ถ๋ฆฌ๋ ์ปดํฌ๋ํธ๋ฅผ ๊ฒ์ ํ๋ค์ $modal์ ์ฐพ์์ฃผ๋ฉด ๋ฉ๋๋ค.
const useModal = () => getCurrentInstance()?.appContext?.app?.config?.globalProperties?.$modal;
export default useModal;
๊ทธ๋ผ setup ๋ฌธ๋ฒ์์๋ ์ด๋ ๊ฒ ์ฌ์ฉ์ด ๋์ด์ง์ ์๊ฒ ๋ค์.
<script setup>
import useModal from '@/modal/useModal';
import SimpleModal from '@/components/SimpleModal';
const modal = useModal();
const onClick = async () => {
const value = await modal.addModal('SimpleModal', SimpleModal, { props: { name: 'eddie' } });
alert(value);
};
</script>
๐ ๊ฒฐ๋ก
์ด๋ ๊ฒ ํ๋ฒ vue์์ ๋ชจ๋ฌ์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด์์ต๋๋ค. (ํน์ ๋ ์ข์ ์๊ฒฌ์์ผ์๋ค๋ฉด ์์ ๋กญ๊ฒ ๋๊ธ ๋ฌ์์ฃผ์ธ์. ๐๐ปโ๏ธ).
ํน์ ํด๋น ๊ธ์ด ์ด๋ ต๊ณ ๊ตฌํํ๊ธฐ ๊ท์ฐฎ์ผ์๋ค๋ฉด ์ ๊ฐ ๊ณต๊ฐํ ์คํ ์์ค vue3-use-modal๋ฅผ ์ฌ์ฉํด์ฃผ์๋ฉด ๋ ๊ฑฐ์์! ๋ง์ ๊ด์ฌ๊ณผ ์ฌ๋ ๋ถํ๋๋ฆฝ๋๋ค ๐ฆ!
'Vue Study' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
ํ์ฌ vue ํ๋ก์ ํธ vite ์ ์ฉํ๊ธฐ (2) | 2022.01.01 |
---|---|
Vue2 ClientOnly ์ปดํฌ๋ํธ ์ ์๊ธฐ (0) | 2021.07.29 |
Vue2 ๋น๋ ํ์ ์ต์ ํ (0) | 2021.07.29 |
Vue3 - v model (0) | 2020.11.08 |
Vue3 - teleport (0) | 2020.11.08 |