欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > 基于 Arco Design UI 封装的 Modal 组件

基于 Arco Design UI 封装的 Modal 组件

2025/2/23 7:26:14 来源:https://blog.csdn.net/Lpandeng/article/details/144371339  浏览:    关键词:基于 Arco Design UI 封装的 Modal 组件

在日常开发中,Modal 是一个使用频率非常高的 UI 组件。通过封装,我们可以让它更灵活、更便捷地与业务逻辑结合。基于 这篇文章 的启发,我编写了一个基于 Arco Design UI 的 Modal 组件封装。以下是封装的源码及其设计思路。

功能简介
我们封装了一个 modal 函数,能够:

  1. 动态传入内容组件和组件属性;
  2. 支持自定义配置(如标题、按钮文案等);
  3. 自动管理 Modal 的打开、关闭,以及异步状态(如 confirmLoading)。
    通过封装,开发者只需调用一个函数,即可快速创建一个带有逻辑控制的弹窗,避免重复性代码。

源码实现
以下是完整源码,包含核心逻辑和注释。


// modal.ts
import {createVNode,render as vueRender,DefineComponent,PropType,
} from "vue";
import { Modal as ArcoModal, ModalConfig } from "@arco-design/web-vue";// 扩展 ModalConfig 类型,添加 confirmLoading 属性
interface ExtendedModalConfig extends ModalConfig {confirmLoading?: boolean;
}/*** 创建一个动态 Modal 的封装* @param {DefineComponent} content - 要显示在 Modal 中的内容组件* @param {Record<string, any>} props - 传递给内容组件的属性* @param {Omit<ExtendedModalConfig, 'visible'>} config - Modal 的配置选项,排除 'visible'*/
export default function modal<T extends DefineComponent>(content: T,props: InstanceType<T>["$props"],config: Omit<ExtendedModalConfig, "visible">
) {const container = document.createElement("div");const _contentVnode = createVNode(content, props);const metadata = Object.create({okText: "确定",cancelText: "取消",visible: true,...config,});// 关闭弹窗逻辑function close() {metadata.visible = false;update();setTimeout(() => vueRender(null, container), 300);}// 更新弹窗配置function update(newConfig?: Partial<ExtendedModalConfig>) {Object.assign(metadata, newConfig);vueRender(createVNode(ArcoModal, metadata, {default: () => _contentVnode,}),container);}metadata.onCancel = async function (...arg: any[]) {await config.onCancel?.(...arg);close();};metadata.onOk = async function () {if (typeof config.onOk !== "function") {close();return;}const result = config.onOk() as Promise<any> | unknown;if (!(result instanceof Promise)) {close();return;}update({ confirmLoading: true });return result.then(() => {update({ confirmLoading: false });close();}).catch(() => {update({ confirmLoading: false });});};// 初次渲染update();document.body.appendChild(container);
}

核心设计思路

  1. 动态创建容器
    我们通过 document.createElement(‘div’) 创建了一个 DOM 容器,并在 document.body 中插入,以便动态渲染 Modal。

  2. 使用 createVNode 和 vueRender
    createVNode 用于生成内容组件的虚拟节点;
    vueRender 负责将 Modal 渲染到指定的容器中。

  3. 配置属性的动态更新
    将 ArcoModal 的所有配置存储在 metadata 中;
    通过 update 函数,可以动态更新配置,比如设置 confirmLoading 状态。

  4. 异步操作的处理
    如果 onOk 返回一个 Promise,则在弹窗确认按钮点击时,显示 loading 状态;
    确认完成后,自动关闭弹窗。
    使用方式

  5. 创建一个内容组件


// MyContentComponent.ts
import { defineComponent } from "vue";export default defineComponent({name: "MyContentComponent",props: {title: String,},setup(props) {return () => <div>标题:{props.title}</div>;},
});
7. 调用封装的 modal 函数
import modal from "./modal";
import MyContentComponent from "./MyContentComponent";modal(MyContentComponent, { title: "动态弹窗" }, {title: "这是一个标题",onOk: () => {return new Promise((resolve) => {setTimeout(() => {console.log("确认操作完成");resolve(true);}, 2000);});},onCancel: () => {console.log("取消操作");},
});
  1. 效果展示
  • 弹窗内容为 MyContentComponent;
  • 点击确认时,显示加载状态(2 秒后关闭弹窗);
  • 点击取消时,仅关闭弹窗。
    优化点和未来改进
  • 事件监听清理:弹窗关闭后,应清理挂载的 DOM 节点,防止内存泄漏。
    更加灵活的样式支持:可以通过额外的 class 或 style 配置,定制化样式。
    多实例支持:扩展当前实现,使其支持多个弹窗同时存在。
    通过以上封装,我们不仅提升了开发效率,也在代码结构上保持了高度的模块化和可读性。这种方法可以灵活地集成到实际业务中,希望对你有所帮助! 😊

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词