核心是四层解耦:ui壳子、业务内容、状态流转、调用方式;通过插槽+props分离内容与容器,v-model:open统一控制显隐,内置表单验证与防抖,支持模板注册和promise返回。

直接封装一个可复用、高可用的弹窗组件,核心不是“写得多”,而是“分得清”——把 UI 壳子、业务内容、状态流转、调用方式四层逻辑彻底解耦。Vue 3 的组合式 API + defineProps/defineEmits + 插槽机制,已经足够支撑一套轻量但健壮的封装方案,无需强依赖 h 函数或 createVNode(除非你明确需要命令式调用)。
一、基础结构:用插槽 + props 实现内容与壳子分离
通用 Dialog 组件本质是一个「容器」,它不关心里面是表单、确认提示还是加载中状态,只负责控制显隐、标题、尺寸、按钮行为和基础交互逻辑。
- 接收 title、width、draggable、showFooter 等外观配置作为 props,避免每个页面硬编码样式
-
用默认插槽承载任意业务内容(如
<template><user-form></user-form></template>),不侵入子组件内部 -
用具名插槽接管 footer(如
<template><custom-buttons></custom-buttons></template>),允许覆盖默认取消/确认按钮 - 暴露 close、confirm 两个标准事件,由父组件决定点击后做什么(重置表单?提交请求?仅关闭?)
二、状态管理:用 v-model 双向绑定替代 visible + handler
别再手动维护 visible = ref(false) 和一堆 openXXXDialog() 方法。Vue 3 的 v-model 支持自定义 prop 名(如 v-model:open),让调用更语义化:
- 组件内用
defineModel('open')(或兼容写法modelValue+update:modelValue)统一收口显隐控制 - 点击遮罩、右上角 ×、点击取消按钮时,统一触发
model.value = false - 父组件只需写
<page-modal v-model:open="showEdit"></page-modal>,逻辑干净,响应式天然同步
三、表单集成:内置验证联动与提交防抖
80% 的弹窗承载表单,高频痛点是验证失败还允许点确认、重复提交、关闭后未重置。可在组件内做一层薄封装:
- 接收
rules和formData作为 props,通过ref透传给内部<el-form></el-form> - 确认按钮绑定
@click="handleSubmit",内部自动调用formRef.validate(),验证失败则聚焦首错误项 - 提交中自动禁用按钮、显示 loading,防止重复点击
- 关闭弹窗时,可选触发
formRef.resetFields()(加个autoResetprop 控制)
四、扩展性设计:支持模板注册与异步结果返回
当项目规模变大,可以平滑升级为命令式调用,但不必从第一天就上复杂方案:
- 先提供
useDialog()组合函数,内部用createVNode + render动态挂载,返回 Promise —— 适合拦截器、工具函数等无上下文场景 - 把常用弹窗(登录、删除确认、编辑表单)提前注册为命名模板,调用时传 key 即可:
dialog('edit-user', { id: 123 }) - 确保传递
appContext,让动态渲染的组件能正常使用 Element Plus 全局组件、指令、插件
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











