|
1 | 1 | import type { Component, HTMLAttributes } from 'vue' |
2 | | -import { isVNode } from 'vue' |
| 2 | +import { createVNode, isVNode, render } from 'vue' |
3 | 3 | import Modal from './index.vue' |
4 | 4 |
|
5 | 5 | export interface ModalProps { |
@@ -67,36 +67,49 @@ export function useFaModal() { |
67 | 67 | const container = document.createElement('div') |
68 | 68 | const visible = ref(false) |
69 | 69 | const options = reactive({ ...initialOptions }) |
70 | | - const app = createApp({ |
71 | | - render() { |
72 | | - return h(Modal, Object.assign({ |
73 | | - 'id': useId(), |
74 | | - 'modelValue': visible.value, |
75 | | - 'onUpdate:modelValue': (val: boolean) => { |
76 | | - visible.value = val |
77 | | - }, |
78 | | - }, options), { |
79 | | - default: () => { |
80 | | - if (typeof options.content === 'string') { |
81 | | - return options.content |
82 | | - } |
83 | | - else if (isVNode(options.content)) { |
84 | | - return options.content |
85 | | - } |
86 | | - else if (options.content) { |
87 | | - return h(options.content) |
88 | | - } |
89 | | - return null |
90 | | - }, |
91 | | - }) |
92 | | - }, |
93 | | - }) |
94 | | - // 继承主应用的上下文 |
95 | 70 | const instance = getCurrentInstance() |
96 | | - if (instance && instance.appContext) { |
97 | | - Object.assign(app._context, instance.appContext) |
| 71 | + let vnode: VNode | null = null |
| 72 | + |
| 73 | + const updateVNode = () => { |
| 74 | + vnode = createVNode(Modal, Object.assign({ |
| 75 | + 'id': instance && instance.uid ? `FaModal-${instance.uid}` : undefined, |
| 76 | + 'modelValue': visible.value, |
| 77 | + 'onUpdate:modelValue': (val: boolean) => { |
| 78 | + visible.value = val |
| 79 | + }, |
| 80 | + ...options, |
| 81 | + }), { |
| 82 | + default: () => { |
| 83 | + if (typeof options.content === 'string') { |
| 84 | + return options.content |
| 85 | + } |
| 86 | + else if (isVNode(options.content)) { |
| 87 | + return options.content |
| 88 | + } |
| 89 | + else if (options.content) { |
| 90 | + return h(options.content) |
| 91 | + } |
| 92 | + return null |
| 93 | + }, |
| 94 | + }) |
| 95 | + // 继承主应用的上下文 |
| 96 | + if (instance && instance.appContext) { |
| 97 | + vnode.appContext = instance.appContext |
| 98 | + } |
| 99 | + render(vnode, container) |
98 | 100 | } |
99 | | - app.mount(container) |
| 101 | + |
| 102 | + // 监听 visible 和 options 变化,自动重新渲染 |
| 103 | + watch([visible, options], () => { |
| 104 | + updateVNode() |
| 105 | + }, { |
| 106 | + immediate: true, |
| 107 | + deep: true, |
| 108 | + }) |
| 109 | + |
| 110 | + // 挂载到当前实例 |
| 111 | + instance?.proxy?.$el?.appendChild(container) |
| 112 | + |
100 | 113 | const open = () => { |
101 | 114 | visible.value = true |
102 | 115 | } |
@@ -179,8 +192,11 @@ export function useFaModal() { |
179 | 192 | contentClass: 'py-0 min-h-auto', |
180 | 193 | footerClass: 'p-4', |
181 | 194 | } |
182 | | - const { open } = create(Object.assign(defaultOptions, options)) |
| 195 | + const { open, update } = create(Object.assign(defaultOptions, options)) |
183 | 196 | open() |
| 197 | + return { |
| 198 | + update, |
| 199 | + } |
184 | 200 | } |
185 | 201 | return { |
186 | 202 | create, |
|
0 commit comments