--- title: Drawer 抽屉 description: 从屏幕边缘滑出的面板,支持四个方向与边缘拖拽调尺寸 --- # Drawer 抽屉 `Drawer` 从屏幕边缘滑出,视觉重量比 [Modal](/ui/overlay/modal) 轻:它遮挡的是边缘而不是整个画面,用户仍能看到部分页面内容。 ## 何时使用 - 长表单、筛选条件、详情信息:内容多但不需要完全接管屏幕时; - 需要与页面内容对照查看时(抽屉不会把页面完全遮住); - 必须阻断用户操作、或需要强确认时,用 Modal。 ## 基础用法 `v-model:open` 控制显隐;`cancel` 表示「被关闭」(遮罩 / Esc / 关闭按钮)。 ## 四个方向 `placement` 支持 `right`(默认)/ `left` / `top` / `bottom`;左右方向用 `width`,上下方向用 `height` 控制尺寸,缩放手柄也会跟着换方向。 ## 自定义尺寸 尺寸接受数字(px)或任意 CSS 长度(`'60%'`、`'48rem'`);`resizable=false` 可以关掉边缘拖拽。 ## 底部动作与补充信息 `#footer` 放底部动作区;`#extra` 在标题下方补充信息(如「已选 2 个条件」)。 ## Modal 还是 Drawer? | | Modal | Drawer | | --- | --- | --- | | 遮挡范围 | 整个页面(居中/贴顶面板) | 一侧边缘 | | 适合内容 | 短表单、确认、需要强聚焦 | 长表单、筛选、详情、多步骤 | | 页面上下文 | 被遮罩挡住 | 仍可见(便于对照) | | 尺寸调整 | 四边缩放 + 全屏 | 单边拖拽 | ## API ### Props | 名称 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `open` | `boolean` | — | 受控打开状态;不传即非受控 | | `defaultOpen` | `boolean` | `false` | 非受控时的初始状态 | | `title` | `string` | `''` | 标题 | | `placement` | `'left' \| 'right' \| 'top' \| 'bottom'` | `'right'` | 滑出方向 | | `width` | `number \| string` | `378` | 宽度(`left` / `right` 生效) | | `height` | `number \| string` | `378` | 高度(`top` / `bottom` 生效) | | `mask` | `boolean` | `true` | 是否显示遮罩 | | `maskClosable` | `boolean` | `true` | 点击遮罩关闭 | | `keyboard` | `boolean` | `true` | Esc 关闭 | | `closable` | `boolean` | `true` | 显示右上角关闭按钮 | | `resizable` | `boolean` | `true` | 允许拖拽面板边缘调整尺寸 | | `popupContainer` | `PopupContainer` | ConfigProvider 配置 | 挂载容器,默认 `body` | ### Events | 名称 | 参数 | 说明 | | --- | --- | --- | | `update:open` | `(open: boolean)` | 打开状态变化 | | `cancel` | `()` | 遮罩 / Esc / 关闭按钮触发的关闭意图(内容区的操作按钮不会触发它) | | `closed` | `()` | 退场动画结束(滚动已解锁、焦点已归还) | ### Slots | 名称 | 参数 | 说明 | | --- | --- | --- | | `default` | — | 内容区(可滚动) | | `extra` | — | 标题下方的补充信息 | | `footer` | — | 底部动作区 | ### 类型定义 ```ts export type DrawerPlacement = 'left' | 'right' | 'top' | 'bottom' export interface DrawerProps { open?: boolean defaultOpen?: boolean title?: string placement?: DrawerPlacement width?: number | string height?: number | string mask?: boolean maskClosable?: boolean keyboard?: boolean closable?: boolean resizable?: boolean popupContainer?: PopupContainer } ``` ## 实现说明 - 面板贴边、容器 `pointer-events: none`,只有面板自身可交互——这样「抽屉打开时页面其他区域仍可点击」,符合抽屉"不接管屏幕"的定位; - 滑入/滑出用 `transform: translateX/Y(±100%)`,只过渡 `transform`,因此不会有布局抖动; - 缩放手柄只改一个轴(左右改宽、上下改高),并按视口上限夹取;关闭后尺寸复位,下次打开不继承; - 焦点与滚动处理与 Modal 共用同一套工具(焦点陷阱、滚动锁引用计数、退场后再归还焦点)。