Skip to content

Commit 9c55835

Browse files
committed
fix: cleanup code, fix keepAlive and extract createH to h.ts
1 parent 18a7c4f commit 9c55835

File tree

6 files changed

+69
-40
lines changed

6 files changed

+69
-40
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import type { App, CSSProperties, Component, ComponentInternalInstance, FunctionalComponent, Raw, Ref, VNode } from 'vue'
1+
import type { App, CSSProperties, Component, ComponentInternalInstance, FunctionalComponent, Raw, Ref } from 'vue'
22
import type { ComponentProps, ComponentSlots } from './Component'
3+
import type { H } from './h'
34

45
export type ModalId = number | string | symbol
56
export type StyleValue = string | CSSProperties | (string | CSSProperties)[]
@@ -41,8 +42,7 @@ export type Vfm = {
4142
modals: ComponentInternalInstance[]
4243
openedModals: ComponentInternalInstance[]
4344
openedModalOverlays: ComponentInternalInstance[]
44-
dynamicModals: VNode[]
45-
modalsContainers: Ref<symbol[]>
45+
h: H
4646
get: (modalId: ModalId) => undefined | ComponentInternalInstance
4747
toggle: (modalId: ModalId, show?: boolean) => undefined | Promise<string>
4848
open: (modalId: ModalId) => undefined | Promise<string>

packages/vue-final-modal/src/components/DynamicModal.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Component, PropType } from 'vue'
22
import { defineComponent, h } from 'vue'
33
import type { ModalSlotOptions, UseModalOptions, UseModalOptionsPrivate } from '..'
4-
import { destroyVNode, isModalSlotOptions, useVfm } from '~/useApi'
4+
import { isModalSlotOptions } from '~/useApi'
55
import { isString, objectEntries } from '~/utils'
66

77
export const DynamicModal = defineComponent({
@@ -13,7 +13,6 @@ export const DynamicModal = defineComponent({
1313
},
1414
},
1515
setup(props) {
16-
const { dynamicModals } = useVfm()
1716
function renderDynamicModal(modal: (UseModalOptions<Component> & UseModalOptionsPrivate)) {
1817
if (!modal.component)
1918
return null
@@ -39,15 +38,7 @@ export const DynamicModal = defineComponent({
3938
if (onUpdateModelValue)
4039
onUpdateModelValue(value)
4140
},
42-
'on_closed': () => {
43-
modal?.resolveClosed?.()
44-
if (!modal.keepAlive) {
45-
const vNode = dynamicModals.find(component => component.key === modal.id)
46-
if (!vNode)
47-
return
48-
destroyVNode(vNode)
49-
}
50-
},
41+
'on_closed': () => modal?.resolveClosed?.(),
5142
'on_opened': () => modal?.resolveOpened?.(),
5243
}, slots)
5344
}

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,20 @@ import { useVfm } from '~/useApi'
44
export const ModalsContainer = defineComponent({
55
name: 'ModalsContainer',
66
setup() {
7-
const { modalsContainers, dynamicModals } = useVfm()
7+
const { h } = useVfm()
88

99
const uid = Symbol(__DEV__ ? 'ModalsContainer' : '')
10-
const shouldMount = computed(() => uid === modalsContainers.value?.[0])
10+
const shouldMount = computed(() => uid === h.containers.value?.[0])
1111

12-
modalsContainers.value.push(uid)
12+
h.containers.value.push(uid)
1313
onBeforeUnmount(() => {
14-
modalsContainers.value = modalsContainers.value.filter(i => i !== uid)
14+
h.containers.value = h.containers.value.filter(i => i !== uid)
1515
})
1616

1717
return () => {
1818
if (!shouldMount.value)
1919
return null
20-
21-
return dynamicModals
20+
return h.vNodes
2221
}
2322
},
2423
})

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { Ref, VNode } from 'vue'
2+
import { ref, shallowReactive } from 'vue'
3+
4+
export type H = {
5+
vNodes: VNode[]
6+
containers: Ref<symbol[]>
7+
push: (vNode: VNode) => void
8+
remove: (vNode: VNode) => void
9+
}
10+
11+
export function createH(): H {
12+
const vNodes: VNode[] = shallowReactive([])
13+
const containers = ref<symbol[]>([])
14+
15+
function push(vNode: VNode) {
16+
if (!vNodes.includes(vNode))
17+
vNodes.push(vNode)
18+
}
19+
20+
function remove(vNode: VNode): void {
21+
const index = vNodes.indexOf(vNode)
22+
if (index !== undefined && index !== -1)
23+
vNodes.splice(index, 1)
24+
}
25+
26+
const _h: H = {
27+
vNodes,
28+
containers,
29+
push,
30+
remove,
31+
}
32+
return _h
33+
}

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import type { App, ComponentInternalInstance, ComputedRef, VNode } from 'vue'
1+
import type { App, ComponentInternalInstance, ComputedRef } from 'vue'
22
import { getCurrentInstance, inject, markRaw, ref, shallowReactive } from 'vue'
33
import { vfmSymbol } from './injectionSymbols'
44
import type { ModalExposed, ModalId, Vfm } from './Modal'
55
import { noop } from './utils'
6+
import { createH } from './h'
67

78
// eslint-disable-next-line import/no-mutable-exports
89
export let activeVfm: Vfm | undefined
@@ -15,8 +16,12 @@ export const defaultVfm: Vfm = {
1516
modals: [],
1617
openedModals: [],
1718
openedModalOverlays: [],
18-
dynamicModals: [],
19-
modalsContainers: ref([]),
19+
h: {
20+
vNodes: [],
21+
containers: ref([]),
22+
push: noop,
23+
remove: noop,
24+
},
2025
get: () => undefined,
2126
toggle: () => undefined,
2227
open: () => undefined,
@@ -31,8 +36,6 @@ export function createVfm() {
3136
const modals: ComponentInternalInstance[] = shallowReactive([])
3237
const openedModals: ComponentInternalInstance[] = shallowReactive([])
3338
const openedModalOverlays: ComponentInternalInstance[] = shallowReactive([])
34-
const dynamicModals: VNode[] = shallowReactive([])
35-
const modalsContainers = ref<symbol[]>([])
3639

3740
const vfm: Vfm = markRaw({
3841
install(app: App) {
@@ -42,8 +45,7 @@ export function createVfm() {
4245
modals,
4346
openedModals,
4447
openedModalOverlays,
45-
dynamicModals,
46-
modalsContainers,
48+
h: createH(),
4749
get(modalId: ModalId) {
4850
return modals.find(modal => getModalExposed(modal)?.value.modalId?.value === modalId)
4951
},

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

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,15 @@ export function useModal<T extends Component = typeof VueFinalModal>(_options: U
6262
id,
6363
modelValue: !!_options?.defaultModelValue,
6464
resolveOpened: () => { },
65-
resolveClosed: () => { },
65+
resolveClosed: tryRemoveVNode,
6666
attrs: {},
6767
...withMarkRaw<T>(_options),
6868
}) as UseModalOptions<T> & UseModalOptionsPrivate
6969

7070
const vNode = h(DynamicModal, { modal: options, key: id })
7171

7272
tryOnUnmounted(() => {
73-
if (options?.keepAlive)
74-
return
75-
destroyVNode(vNode)
73+
tryRemoveVNode()
7674
})
7775

7876
if (options.modelValue === true)
@@ -82,7 +80,7 @@ export function useModal<T extends Component = typeof VueFinalModal>(_options: U
8280
if (options.modelValue)
8381
return Promise.resolve('[Vue Final Modal] modal is already opened.')
8482

85-
destroyVNode(vNode)
83+
tryRemoveVNode()
8684
options.modelValue = true
8785
pushVNode(vNode)
8886

@@ -97,10 +95,19 @@ export function useModal<T extends Component = typeof VueFinalModal>(_options: U
9795

9896
options.modelValue = false
9997
return new Promise((resolve) => {
100-
options.resolveClosed = () => resolve('closed')
98+
options.resolveClosed = () => {
99+
resolve('closed')
100+
tryRemoveVNode()
101+
}
101102
})
102103
}
103104

105+
function tryRemoveVNode() {
106+
if (options.keepAlive)
107+
return
108+
removeVNode(vNode)
109+
}
110+
104111
function patchOptions(_options: Partial<UseModalOptions<T>>) {
105112
const { slots, ...rest } = withMarkRaw(_options, options.component)
106113

@@ -131,7 +138,7 @@ export function useModal<T extends Component = typeof VueFinalModal>(_options: U
131138
open,
132139
close,
133140
patchOptions,
134-
destroy: () => destroyVNode(vNode),
141+
destroy: () => removeVNode(vNode),
135142
}
136143
}
137144

@@ -156,7 +163,7 @@ function patchAttrs<T extends Record<string, any>>(attrs: T, newAttrs: Partial<T
156163

157164
async function pushVNode(vNode: VNode) {
158165
const vfm = await useSsrVfm()
159-
vfm?.dynamicModals.push(vNode)
166+
vfm.h.push(vNode)
160167
}
161168

162169
/** nextTick will break the SSR, so use `activeVfm` first and then `useVfm()` */
@@ -170,12 +177,9 @@ async function useSsrVfm(): Promise<Vfm> {
170177
}
171178
}
172179

173-
export function destroyVNode(vNode: VNode): void {
180+
function removeVNode(vNode: VNode): void {
174181
const vfm = useVfm()
175-
176-
const index = vfm?.dynamicModals.indexOf(vNode)
177-
if (index !== undefined && index !== -1)
178-
vfm?.dynamicModals.splice(index, 1)
182+
vfm.h.remove(vNode)
179183
}
180184

181185
export function useModalSlot<T extends Component>(options: {

0 commit comments

Comments
 (0)