FxDrawer 抽屉
从屏幕边缘滑出的浮层。不依赖任何 UI 框架,复用 FxDialog 的核心逻辑,支持四向打开与可调整大小。
基础用法
通过 v-model 控制显隐,title 设置标题。默认从右侧滑出,尺寸 30%。before-close 可拦截关闭。
打开方向
direction 支持 rtl(右)/ ltr(左)/ ttb(上)/ btt(下),size 控制尺寸。
无标题
设置 with-header 为 false 可隐藏标题栏,获得更大空间。如需无障碍,仍应设置 title 属性。
自定义内容
与 Dialog 一样,Drawer 可承载任意内容,包括表单。
自定义标题
header 插槽可自定义标题区。
标题栏额外按钮(扩展)
header-extra 插槽位于关闭按钮左侧,用于放置自定义按钮。
全屏(扩展)
fullscreen 控制是否全屏铺满。FxDrawer 额外提供:fullscreen-button(默认开启,显示标题栏全屏切换按钮)、default-fullscreen(打开时默认全屏)、v-model:fullscreen(受控双向)。全屏时抽屉铺满整个屏幕,size 与 direction 失效。
可调整大小
设置 resizable 后,抽屉边缘出现拖拽条,可拖动调整大小。
嵌套抽屉
嵌套抽屉时内层需设置 append-to-body。
遮罩
modal 为 false 时隐藏遮罩;modal-penetrable 使遮罩可点击穿透(需 modal=false)。
局部引入
ts
import { FxDrawer } from "@fx/components"API
Attributes
继承 FxDialog 全部 Attributes,并扩展:
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| model-value / v-model | 是否显示 | boolean | false |
| title | 标题(也可用 header / title 插槽) | string | — |
| direction | 打开方向 | 'rtl' | 'ltr' | 'ttb' | 'btt' | rtl |
| size | 抽屉尺寸(数字为 px,字符串建议 'x%') | string | number | 30% |
| with-header | 是否显示 header(隐藏可获得更大空间) | boolean | true |
| resizable | 是否可调整大小 | boolean | false |
| modal-fade | 遮罩层淡入淡出开关 | boolean | true |
| fullscreen | 是否全屏铺满(支持 v-model:fullscreen,扩展) | boolean | false |
| fullscreen-button | 是否显示全屏切换按钮(扩展) | boolean | true |
| default-fullscreen | 打开时是否默认全屏(扩展) | boolean | false |
| modal | 是否显示遮罩 | boolean | true |
| modal-penetrable | 遮罩是否可穿透(需 modal=false) | boolean | false |
| modal-class | 遮罩自定义类名 | string | — |
| header-class / body-class / footer-class | header / 正文 / 底部自定义类名 | string | — |
| append-to-body | 是否挂载到 body(嵌套抽屉需置 true) | boolean | false |
| append-to | 挂载目标 | 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 |
| before-close | 关闭前回调,调用 done() 关闭、done(true) 取消 | (done: (cancel?: boolean) => void) => void | — |
| destroy-on-close | 关闭时销毁内容 | boolean | false |
| trap-focus | 是否在抽屉内捕获焦点(焦点陷阱) | boolean | false |
| transition | 自定义过渡动画(字符串名或 TransitionProps) | string | TransitionProps | — |
| z-index | 层级 | number | 自增 |
| header-aria-level | header 的 aria-level | string | 2 |
Events
继承 FxDialog 全部 Events,并扩展:
| 名称 | 说明 | 类型 |
|---|---|---|
| update:modelValue | 显隐变化 | (value: boolean) |
| update:fullscreen | 全屏状态变化(扩展) | (value: boolean) |
| fullscreen-change | 全屏状态变化(扩展) | (value: boolean) |
| open / opened / close / closed | 打开 / 关闭生命周期 | () => void |
| open-auto-focus / close-auto-focus | 聚焦回调 | () => void |
| resize-start | 开始调整大小 | (evt: MouseEvent, size: number) |
| resize | 调整大小中 | (evt: MouseEvent, size: number) |
| resize-end | 结束调整大小 | (evt: MouseEvent, size: number) |
Slots
| 名称 | 说明 | 作用域参数 |
|---|---|---|
| default | 抽屉正文 | — |
| header | 标题区(覆盖默认标题与全屏按钮,不覆盖关闭按钮) | close: () => void titleId: string titleClass: string |
| header-extra | 标题栏额外按钮区(位于全屏 / 关闭按钮左侧,扩展) | — |
| footer | 底部区 | — |
| title | 标题(已废弃,建议改用 header) | — |
Exposes
| 名称 | 说明 | 类型 |
|---|---|---|
| handleClose | 触发关闭(会调用 before-close) | () => void |
实现说明
- 核心复用:抽屉复用
FxDialog的useDialogHook 处理显隐、遮罩、焦点陷阱、滚动锁定、z-index自增等通用弹层逻辑,自身只负责四向定位与可调整大小。 - 尺寸方向:
useResizable根据direction判断横向(ltr/rtl)或纵向(ttb/btt),按方向在抽屉面板上设置width或height。横向抽屉撑满高度、纵向抽屉撑满宽度,再用top/right/bottom/left锚定到对应边缘。 - 可调整大小:
resizable开启后渲染一条贴边的拖拽条(fx-drawer__dragger),mousedown锁定起始尺寸与坐标,mousemove按方向取offsetX或offsetY并以方向符号累加,最终尺寸在[4, 窗口尺寸]区间内 clamp。拖动期间挂is-dragging类关闭过渡,避免拖拽抖动。resize-start/resize/resize-end三个事件携带MouseEvent与当前尺寸。 - 进入 / 离开动画:
fx-drawer-fade过渡。enter-from / leave-to 阶段把遮罩背景置透明并按方向位移抽屉面板(ltr左移 100%、rtl右移 100%、ttb上移 100%、btt下移 100%),duration-slow时长内完成滑入滑出。 - 视觉规格:背景走
--color-surface、阴影走--shadow-card、文字走--color-text-primary,标题与正文统一--fx-drawer-padding-primary(默认 20px)内边距,标题区下方留 32px 间距,底部区域顶部 10px。所有取值统一走@fx/styles设计 token,不引用任何第三方 UI 库变量。 - fx 增强(向后兼容,默认值保持原行为):标题栏右侧的「全屏 / 退出全屏」按钮(
fullscreen-button默认开启)、header-extra插槽用于放置自定义工具按钮、fullscreen/default-fullscreen/v-model:fullscreen三种全屏控制方式。全屏态挂is-fullscreen类,面板铺满整个屏幕,此时size与direction的尺寸约束失效。 - 无障碍:面板挂
role="dialog"、aria-modal="true",标题存在时以aria-label标注,否则用aria-labelledby关联titleId;标题节点role="heading"+header-aria-level;首焦元素fx-drawer__sr-focus在聚焦时去除默认轮廓。
