From 522a97f8d6a1616206a56ccdf4c7a29a4a67a2df Mon Sep 17 00:00:00 2001
From: Hooray <304327508@qq.com>
Date: Tue, 29 Jul 2025 00:57:27 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=20`useFaModal`=20=E5=92=8C?=
=?UTF-8?q?=20`useFaDrawer`?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/ui/components/FaDrawer/index.ts | 71 ++++++++++-------
src/ui/components/FaModal/index.ts | 76 +++++++++++--------
.../component_built_in_example/modal.vue | 31 +++++++-
3 files changed, 118 insertions(+), 60 deletions(-)
diff --git a/src/ui/components/FaDrawer/index.ts b/src/ui/components/FaDrawer/index.ts
index 58d33762..433ebf64 100644
--- a/src/ui/components/FaDrawer/index.ts
+++ b/src/ui/components/FaDrawer/index.ts
@@ -1,5 +1,5 @@
import type { Component, HTMLAttributes } from 'vue'
-import { isVNode } from 'vue'
+import { createVNode, isVNode, render } from 'vue'
import Drawer from './index.vue'
export interface DrawerProps {
@@ -59,36 +59,49 @@ export function useFaDrawer() {
const container = document.createElement('div')
const visible = ref(false)
const options = reactive({ ...initialOptions })
- const app = createApp({
- render() {
- return h(Drawer, Object.assign({
- 'id': useId(),
- 'modelValue': visible.value,
- 'onUpdate:modelValue': (val: boolean) => {
- visible.value = val
- },
- }, options), {
- default: () => {
- if (typeof options.content === 'string') {
- return options.content
- }
- else if (isVNode(options.content)) {
- return options.content
- }
- else if (options.content) {
- return h(options.content)
- }
- return null
- },
- })
- },
- })
- // 继承主应用的上下文
const instance = getCurrentInstance()
- if (instance && instance.appContext) {
- Object.assign(app._context, instance.appContext)
+ let vnode: VNode | null = null
+
+ const updateVNode = () => {
+ vnode = createVNode(Drawer, Object.assign({
+ 'id': instance && instance.uid ? `FaDrawer-${instance.uid}` : undefined,
+ 'modelValue': visible.value,
+ 'onUpdate:modelValue': (val: boolean) => {
+ visible.value = val
+ },
+ ...options,
+ }), {
+ default: () => {
+ if (typeof options.content === 'string') {
+ return options.content
+ }
+ else if (isVNode(options.content)) {
+ return options.content
+ }
+ else if (options.content) {
+ return h(options.content)
+ }
+ return null
+ },
+ })
+ // 继承主应用的上下文
+ if (instance && instance.appContext) {
+ vnode.appContext = instance.appContext
+ }
+ render(vnode, container)
}
- app.mount(container)
+
+ // 监听 visible 和 options 变化,自动重新渲染
+ watch([visible, options], () => {
+ updateVNode()
+ }, {
+ immediate: true,
+ deep: true,
+ })
+
+ // 挂载到当前实例
+ instance?.proxy?.$el?.appendChild(container)
+
const open = () => {
visible.value = true
}
diff --git a/src/ui/components/FaModal/index.ts b/src/ui/components/FaModal/index.ts
index 66ff8118..a662cf87 100644
--- a/src/ui/components/FaModal/index.ts
+++ b/src/ui/components/FaModal/index.ts
@@ -1,5 +1,5 @@
import type { Component, HTMLAttributes } from 'vue'
-import { isVNode } from 'vue'
+import { createVNode, isVNode, render } from 'vue'
import Modal from './index.vue'
export interface ModalProps {
@@ -67,36 +67,49 @@ export function useFaModal() {
const container = document.createElement('div')
const visible = ref(false)
const options = reactive({ ...initialOptions })
- const app = createApp({
- render() {
- return h(Modal, Object.assign({
- 'id': useId(),
- 'modelValue': visible.value,
- 'onUpdate:modelValue': (val: boolean) => {
- visible.value = val
- },
- }, options), {
- default: () => {
- if (typeof options.content === 'string') {
- return options.content
- }
- else if (isVNode(options.content)) {
- return options.content
- }
- else if (options.content) {
- return h(options.content)
- }
- return null
- },
- })
- },
- })
- // 继承主应用的上下文
const instance = getCurrentInstance()
- if (instance && instance.appContext) {
- Object.assign(app._context, instance.appContext)
+ let vnode: VNode | null = null
+
+ const updateVNode = () => {
+ vnode = createVNode(Modal, Object.assign({
+ 'id': instance && instance.uid ? `FaModal-${instance.uid}` : undefined,
+ 'modelValue': visible.value,
+ 'onUpdate:modelValue': (val: boolean) => {
+ visible.value = val
+ },
+ ...options,
+ }), {
+ default: () => {
+ if (typeof options.content === 'string') {
+ return options.content
+ }
+ else if (isVNode(options.content)) {
+ return options.content
+ }
+ else if (options.content) {
+ return h(options.content)
+ }
+ return null
+ },
+ })
+ // 继承主应用的上下文
+ if (instance && instance.appContext) {
+ vnode.appContext = instance.appContext
+ }
+ render(vnode, container)
}
- app.mount(container)
+
+ // 监听 visible 和 options 变化,自动重新渲染
+ watch([visible, options], () => {
+ updateVNode()
+ }, {
+ immediate: true,
+ deep: true,
+ })
+
+ // 挂载到当前实例
+ instance?.proxy?.$el?.appendChild(container)
+
const open = () => {
visible.value = true
}
@@ -179,8 +192,11 @@ export function useFaModal() {
contentClass: 'py-0 min-h-auto',
footerClass: 'p-4',
}
- const { open } = create(Object.assign(defaultOptions, options))
+ const { open, update } = create(Object.assign(defaultOptions, options))
open()
+ return {
+ update,
+ }
}
return {
create,
diff --git a/src/views/component_built_in_example/modal.vue b/src/views/component_built_in_example/modal.vue
index 07aba535..a31f1c00 100644
--- a/src/views/component_built_in_example/modal.vue
+++ b/src/views/component_built_in_example/modal.vue
@@ -87,7 +87,33 @@ function showModalConfirm() {
},
})
}
-
+function showModalDoubleConfirm() {
+ const { update } = useFaModal().confirm({
+ title: '温馨提醒',
+ content: '这是 confirm 弹窗',
+ beforeClose: (action, done) => {
+ if (action === 'confirm') {
+ update({
+ title: '二次确认',
+ content: '确定要关闭吗?',
+ confirmButtonText: '我确定',
+ cancelButtonText: '我取消',
+ beforeClose: (action) => {
+ if (action === 'confirm') {
+ done()
+ }
+ else {
+ done()
+ }
+ },
+ })
+ }
+ else {
+ done()
+ }
+ },
+ })
+}
function showModalPromiseConfirm() {
useFaModal().confirm({
title: '温馨提醒',
@@ -201,6 +227,9 @@ const { open: open2 } = useFaModal().create({
Confirm
+
+ Double Confirm
+
Confirm with promise