Drawer 抽屉
用于从页面边缘滑出临时面板。相比 Dialog,Drawer 更适合较长表单、详情预览、配置侧栏和临时文档展示。
基础用法
使用 v-model 控制抽屉显示状态。direction 控制打开方向,支持 rtl、ltr、ttb、btt;size 控制抽屉尺寸。
vue
<template>
<el-radio-group v-model="direction">
<el-radio-button value="ltr">left to right</el-radio-button>
<el-radio-button value="rtl">right to left</el-radio-button>
<el-radio-button value="ttb">top to bottom</el-radio-button>
<el-radio-button value="btt">bottom to top</el-radio-button>
</el-radio-group>
<el-button type="primary" @click="visible = true">打开抽屉</el-button>
<el-drawer
v-model="visible"
title="项目详情"
:direction="direction"
:before-close="handleClose"
>
<p>这里展示项目基础信息、状态说明或临时配置内容。</p>
</el-drawer>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessageBox } from 'element-plus'
import type { DrawerProps } from 'element-plus'
const visible = ref(false)
const direction = ref<DrawerProps['direction']>('rtl')
const handleClose = (done: () => void) => {
ElMessageBox.confirm('确认关闭抽屉?')
.then(() => done())
.catch(() => {})
}
</script>不添加 Title
当不需要标题栏时,可以设置 with-header="false"。如果应用需要无障碍访问,仍建议提供有意义的 title。
vue
<el-button type="primary" @click="visible = true">打开无标题抽屉</el-button>
<el-drawer v-model="visible" title="无标题抽屉" :with-header="false">
<p>无标题抽屉适合放置简单说明或轻量筛选。</p>
</el-drawer>自定义内容
Drawer 可以承载表格、表单、详情列表等复杂内容,常用于侧边编辑、查看明细和批量配置。
vue
<template>
<el-button text type="primary" @click="tableVisible = true">打开表格抽屉</el-button>
<el-drawer v-model="tableVisible" title="报价明细" size="50%">
<el-table :data="tableData">
<el-table-column prop="name" label="费用项" />
<el-table-column prop="amount" label="金额" />
</el-table>
</el-drawer>
</template>自定义头部
通过 header 插槽可以自定义标题区域。插槽提供 close、titleId、titleClass,用于关闭抽屉和维护可访问性。
vue
<el-drawer v-model="visible" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<h4 :id="titleId" :class="titleClass">项目风险提醒</h4>
<el-button type="danger" @click="close">关闭</el-button>
</template>
<p>当前项目存在物料到货风险。</p>
</el-drawer>可调整抽屉
设置 resizable 后,用户可以拖动抽屉边缘调整尺寸。适合表格、长表单和需要临时扩展查看空间的场景。
vue
<el-drawer v-model="visible" title="可调整抽屉" direction="rtl" resizable>
<p>拖动抽屉边缘即可调整尺寸。</p>
</el-drawer>嵌套抽屉
需要在抽屉中再打开抽屉时,内层 Drawer 应设置 append-to-body,避免层级和定位问题。
vue
<el-drawer v-model="outerVisible" title="外层抽屉" size="50%">
<el-button type="primary" @click="innerVisible = true">打开内层抽屉</el-button>
<el-drawer v-model="innerVisible" title="内层抽屉" append-to-body>
<p>内层抽屉适合展示二级配置。</p>
</el-drawer>
</el-drawer>模态层
默认情况下 Drawer 会显示遮罩层。设置 modal="false" 可以隐藏遮罩层;需要允许点击穿透时,可配合 modal-penetrable 使用。
vue
<el-drawer v-model="visible" :modal="false" modal-penetrable>
<span>这是一个无遮罩抽屉。</span>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="visible = false">确认</el-button>
</template>
</el-drawer>销毁内容
Drawer 的默认插槽是懒渲染的。设置 destroy-on-close 后,抽屉关闭时会销毁内部内容,适合每次打开都需要重新初始化的表单。
vue
<el-drawer v-model="visible" title="临时筛选" destroy-on-close>
<el-form label-width="80px">
<el-form-item label="关键词">
<el-input placeholder="请输入关键词" />
</el-form-item>
</el-form>
</el-drawer>Drawer API
Drawer 属性
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| model-value / v-model | 是否显示 Drawer | boolean | false |
| append-to-body | Drawer 是否插入至 body,嵌套 Drawer 需要设置为 true | boolean | false |
| append-to | Drawer 挂载到哪个 DOM 元素,会覆盖 append-to-body | CSSSelector | HTMLElement | body |
| lock-scroll | Drawer 出现时是否锁定 body 滚动 | boolean | true |
| before-close | 关闭前回调,会暂停 Drawer 的关闭 | function | - |
| close-on-click-modal | 是否可以通过点击遮罩关闭 Drawer | boolean | true |
| close-on-press-escape | 是否可以通过按下 ESC 关闭 Drawer | boolean | true |
| open-delay | 打开延时时间,单位毫秒 | number | 0 |
| close-delay | 关闭延时时间,单位毫秒 | number | 0 |
| destroy-on-close | 关闭后是否销毁子元素 | boolean | false |
| modal | 是否需要遮罩层 | boolean | true |
| modal-penetrable | 是否允许穿透遮罩层,需配合 modal="false" 使用 | boolean | false |
| direction | Drawer 打开方向 | rtl | ltr | ttb | btt | rtl |
| resizable | 是否启用可调整大小 | boolean | false |
| show-close | 是否显示关闭按钮 | boolean | true |
| size | Drawer 窗体大小,数字按像素处理,字符串可传百分比 | number | string | 30% |
| title | Drawer 标题,也可通过 header 插槽传入 | string | - |
| with-header | 是否显示 header 栏 | boolean | true |
| modal-class | 遮罩层自定义类名 | string | - |
| header-class | header 部分自定义类名 | string | - |
| body-class | body 部分自定义类名 | string | - |
| footer-class | footer 部分自定义类名 | string | - |
| z-index | 设置 z-index | number | - |
| header-aria-level | header 的 aria-level 属性 | string | 2 |
Drawer 事件
| 事件名 | 说明 | 类型 |
|---|---|---|
| open | Drawer 打开时触发 | Function |
| opened | Drawer 打开动画结束时触发 | Function |
| close | Drawer 关闭时触发 | Function |
| closed | Drawer 关闭动画结束时触发 | Function |
| open-auto-focus | 输入焦点聚焦到 Drawer 内容时触发 | Function |
| close-auto-focus | 输入焦点从 Drawer 内容失焦时触发 | Function |
| resize-start | 开始调整大小时触发,需启用 resizable | Function |
| resize | 调整大小时触发,需启用 resizable | Function |
| resize-end | 调整大小结束时触发,需启用 resizable | Function |
Drawer 插槽
| 插槽名 | 说明 |
|---|---|
| default | Drawer 内容 |
| header | Drawer 标题区域,会替换标题部分但不会移除关闭按钮 |
| footer | Drawer 页脚部分 |
Drawer 暴露
| 名称 | 说明 | 类型 |
|---|---|---|
| handleClose | 用于关闭 Drawer,会调用传入的 before-close 方法 | Function |

