Skip to content

Commit ef35c1e

Browse files
committed
refactor: rewrite ModalsContainer with render function
1 parent 3c589ff commit ef35c1e

File tree

4 files changed

+69
-58
lines changed

4 files changed

+69
-58
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import type { Component } from 'vue-demi'
2+
import { computed, defineComponent, h, onBeforeUnmount } from 'vue-demi'
3+
import type { ModalSlotOptions } from '..'
4+
import { isModalSlotOptions, useVfm } from '~/useApi'
5+
import { isString, objectEntries } from '~/utils'
6+
7+
export const ModalsContainer = defineComponent({
8+
setup() {
9+
const { modalsContainers, dynamicModals } = useVfm()
10+
11+
const uid = Symbol(__DEV__ ? 'ModalsContainer' : '')
12+
const shouldMount = computed(() => uid === modalsContainers.value?.[0])
13+
14+
modalsContainers.value.push(uid)
15+
onBeforeUnmount(() => {
16+
modalsContainers.value = modalsContainers.value.filter(i => i !== uid)
17+
})
18+
19+
function resolvedClosed(index: number) {
20+
dynamicModals[index]?.resolveClosed?.()
21+
if (!dynamicModals[index]?.keepAlive)
22+
dynamicModals.splice(index, 1)
23+
}
24+
25+
function resolvedOpened(index: number) {
26+
dynamicModals[index]?.resolveOpened?.()
27+
}
28+
29+
return () => {
30+
if (shouldMount.value)
31+
return null
32+
return dynamicModals.map((modal, index) => {
33+
if (!modal.component)
34+
return null
35+
const slots = objectEntries(modal.slots || {}).reduce((acc, cur) => {
36+
const slotName = cur[0] as string
37+
const slot = cur[1] as string | Component | ModalSlotOptions
38+
if (isString(slot))
39+
acc[slotName] = () => h('div', { innerHTML: slot })
40+
else if (isModalSlotOptions(slot))
41+
acc[slotName] = () => h(slot.component, slot.attrs)
42+
else
43+
acc[slotName] = () => h(slot)
44+
return acc
45+
}, {} as any)
46+
47+
return h(modal.component, {
48+
'key': modal.id,
49+
'modelValue': modal.modelValue,
50+
'onUpdate:modelValue': (value: boolean) => modal.modelValue = value,
51+
'displayDirective': modal?.keepAlive ? 'show' : undefined,
52+
...(typeof modal.attrs === 'object' ? modal.attrs : {}),
53+
'on_closed': () => resolvedClosed(index),
54+
'on_opened': () => resolvedOpened(index),
55+
}, slots)
56+
})
57+
}
58+
},
59+
})

packages/vue-final-modal/src/components/ModalsContainer.vue

Lines changed: 0 additions & 57 deletions
This file was deleted.

packages/vue-final-modal/src/components/VueFinalModal/VueFinalModal.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ export interface VueFinalModalEmits {
2424
2525
/** onClickOutside will only be emitted when clickToClose equal to `false` */
2626
(e: 'clickOutside'): void
27+
28+
/** Internal event, only used in ModalsContainer */
29+
(e: '_opened'): void
30+
/** Internal event, only used in ModalsContainer */
31+
(e: '_closed'): void
2732
}
2833
2934
const props = defineProps(vueFinalModalProps)
@@ -75,13 +80,17 @@ const {
7580
},
7681
onEnter() {
7782
emit('opened')
83+
// eslint-disable-next-line vue/custom-event-name-casing
84+
emit('_opened')
7885
resolveToggle('opened')
7986
},
8087
onLeave() {
8188
arrayRemoveItem(openedModals, instance)
8289
resetZIndex()
8390
enableBodyScroll()
8491
emit('closed')
92+
// eslint-disable-next-line vue/custom-event-name-casing
93+
emit('_closed')
8594
resolveToggle('closed')
8695
},
8796
})

packages/vue-final-modal/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import ModalsContainer from './components/ModalsContainer.vue'
1+
import { ModalsContainer } from './components/ModalsContainer'
22
import VueFinalModal from './components/VueFinalModal/VueFinalModal.vue'
33

44
import type { Vfm } from './Modal'

0 commit comments

Comments
 (0)