FxDialog 对话框
在当前页面正中弹出浮层,承载表单、确认、详情等内容。不依赖任何 UI 框架,扩展「全屏切换按钮」与 header-extra 插槽。
基础用法
通过 v-model 双向绑定控制显隐,title 设置标题,footer 插槽放置操作按钮。before-close 可拦截关闭。
自定义内容
Dialog 的内容可以是任意内容,包括表单、表格等。
自定义标题
header 插槽可自定义标题区。为保持无障碍,请配合 title 属性,或用 titleId 作用域参数指定标题元素。
嵌套对话框
Dialog 嵌套时,内层需设置 append-to-body,以正确层叠渲染。
内容居中
设置 center 后,header 与 footer 水平居中(不影响 body)。
水平垂直居中
设置 align-center 使弹窗水平 + 垂直居中,此时 top 不生效。
关闭时销毁
开启 destroy-on-close 后,关闭时销毁默认插槽内容,再次打开重新挂载。
可拖拽
设置 draggable 开启拖拽,overflow 允许拖出可视区。
全屏
fullscreen 控制是否全屏。FxDialog 额外提供:fullscreen-button(默认开启,显示标题栏全屏切换按钮)、default-fullscreen(打开时默认全屏)、v-model:fullscreen(受控双向)。
标题栏额外按钮(扩展)
header-extra 插槽位于全屏按钮左侧,用于放置刷新、导出、设置等自定义按钮。
遮罩
modal 为 false 时隐藏遮罩;modal-class 自定义遮罩样式;modal-penetrable 使遮罩可点击穿透(需 modal=false)。
自定义动画
transition 接受动画名字符串或 Vue Transition 配置对象。Dialog 通过 Teleport 渲染到 body,动画类需用全局样式定义。
事件
打开浏览器控制台,观察事件触发顺序:open → opened → close → closed。
实现说明
架构分层
FxDialog 拆为两层,与 fxOverlay / fxFocusTrap 协作:
- FxDialog(
dialog.vue):负责挂载位置(Teleport)、遮罩、焦点陷阱、显隐动画生命周期、全屏状态管理,向内容层provide(dialogInjectionKey)。 - FxDialogContent(
dialog-content.vue):负责 header / body / footer 三段式结构、关闭按钮、全屏切换按钮、拖拽(基于_shared/use-draggable),通过inject拿到容器注入的 ref 与状态。
显隐与动画
- 由
use-dialog.ts集中管理visible/rendered/closing状态:openDelay/closeDelay控制延时,destroy-on-close控制关闭后是否销毁(懒渲染)。 - 动画名默认
dialog-fade(遮罩淡入淡出 + 弹窗位移淡入),样式定义在dialog.vue的全局<style>块(.dialog-fade-enter-active/.dialog-fade-leave-active+@keyframes)。因弹窗 Teleport 到 body,自定义动画类需写在全局(非 scoped)样式中。 transition支持字符串(动画名)或 Vue Transition 配置对象;传对象时若无name,自动回退到dialog-fade并触发警告。
全屏能力(fx 增强)
- 受控全屏:
v-model:fullscreen双向绑定,内部以isFullscreen维护真实状态,打开时取fullscreen ?? defaultFullscreen初始化。 - 全屏切换按钮:
fullscreen-button(默认开启),位于标题栏,点击触发update:fullscreen/fullscreen-change事件。 - 全屏时禁用拖拽与遮罩穿透,并保留 / 恢复拖拽产生的
transform偏移。
关闭流程
关闭可被 before-close 拦截:回调收到 done(cancel?),调用 done(true) 取消关闭,done() 或 done(false) 继续关闭。触发关闭的入口(关闭按钮 / 遮罩点击 / ESC)统一走 handleClose。
样式与 token
- 类名走
useNamespace('dialog')生成fx-BEM(脚本内),<style>内手写字面量但遵循同一 BEM 结构。 - 视觉规格映射到
@fx/stylestoken:背景--color-surface、阴影--shadow-card、圆角--radius-sm、标题色--color-text-primary、正文色--color-text-secondary、过渡时长--duration-slow;不引用任何第三方 UI 库的 CSS 变量。 - 局部 CSS 变量(
--fx-dialog-*)承担尺寸 / 字号 / 间距的可定制入口,消费方可通过覆盖这些变量微调。
局部引入
ts
import { FxDialog } from "@fx/components"API
Attributes
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| model-value (v-model) | 是否显示 | boolean | false |
| title | 标题(也可用 header 插槽) | string | '' |
| width | 宽度 | string | number | 50% |
| fullscreen | 是否全屏(支持 v-model:fullscreen) | boolean | false |
| fullscreen-button | 是否显示全屏切换按钮(扩展) | boolean | true |
| default-fullscreen | 打开时是否默认全屏(扩展) | boolean | false |
| top | margin-top 值 | string | 15vh |
| modal | 是否显示遮罩 | boolean | true |
| modal-penetrable | 遮罩是否可穿透(需 modal=false) | boolean | false |
| modal-class | 遮罩自定义类名 | string | — |
| header-class / body-class / footer-class | 各区域自定义类名 | string | — |
| append-to-body | 是否挂载到 body(嵌套 Dialog 需置 true) | boolean | false |
| append-to | 挂载目标(覆盖 append-to-body) | string | HTMLElement | body |
| lock-scroll | 是否锁定 body 滚动 | boolean | true |
| open-delay / close-delay | 打开 / 关闭延时(ms) | number | 0 |
| close-on-click-modal | 点击遮罩是否关闭 | boolean | true |
| close-on-press-escape | 按 ESC 是否关闭 | boolean | true |
| show-close | 是否显示关闭按钮 | boolean | true |
| close-icon | 自定义关闭图标。字符串为 IconString 类型(即 FxIcon 图标名,如 ep:edit、ant-design:home、svg:xxx) | string | ep:close |
| before-close | 关闭前回调 | (done: (cancel?: boolean) => void) => void | — |
| draggable | 是否可拖拽 | boolean | false |
| overflow | 可拖拽时是否允许超出可视区 | boolean | false |
| center | 是否居中显示 header 与 footer | boolean | false |
| align-center | 是否水平 + 垂直居中 | boolean | false |
| destroy-on-close | 关闭时销毁内容 | boolean | false |
| z-index | 层级 | number | 自增 |
| header-aria-level | header 的 aria-level | string | 2 |
| transition | 自定义动画配置 | string | TransitionProps | dialog-fade |
| trap-focus | 是否在弹窗内捕获焦点(历史兼容字段,弹窗默认即做焦点陷阱,传值不影响行为) | boolean | false |
Events
| 名称 | 说明 | 类型 |
|---|---|---|
| update:modelValue | 显隐变化 | (value: boolean) |
| update:fullscreen | 全屏状态变化(扩展) | (value: boolean) |
| fullscreen-change | 全屏状态变化(扩展) | (value: boolean) |
| open | 打开瞬间 | () => void |
| opened | 打开动画结束 | () => void |
| close | 关闭瞬间 | () => void |
| closed | 关闭动画结束 | () => void |
| open-auto-focus | 打开并聚焦后 | () => void |
| close-auto-focus | 关闭并聚焦后 | () => void |
Slots
| 名称 | 说明 | 作用域参数 |
|---|---|---|
| default | 正文内容 | — |
| header | 标题区(覆盖默认标题,不覆盖关闭按钮) | close titleId titleClass |
| header-extra | 标题栏额外按钮区(全屏按钮左侧,扩展) | fullscreen toggleFullscreen |
| footer | 底部区 | — |
| title | 标题(已废弃,用 header) | — |
Exposes
| 名称 | 说明 | 类型 |
|---|---|---|
| resetPosition | 重置拖拽位置 | () => void |
| handleClose | 触发关闭 | () => void |
