Drawer 抽屉
有些时候,Dialog 组件并不满足我们的需求,比如你的表单很长,亦或是你需要临时展示一些文档,此时可以使用 Drawer。它拥有和 Dialog 几乎相同的 API,并在 UI 上带来不一样的体验。
ts
import { Drawer as ElDrawer } from '@szhn/dh-design-pc'基础用法
通过 v-model 控制 Drawer 的显示与隐藏。默认情况下 Drawer 从右侧打开,占据 35% 的浏览器宽度,并展示标准底部操作区,可通过 direction 和 size 修改。
<template>
<div>
<el-button @click="drawer = true">打开抽屉</el-button>
<el-drawer v-model="drawer" title="抽屉标题">
<p>这里是抽屉内容区域,可以放置任意 Vue 组件。</p>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Drawer as ElDrawer, Button as ElButton } from '@szhn/dh-design-pc'
const drawer = ref(false)
</script>不同方向
通过 direction 属性设置 Drawer 的打开方向,支持 rtl / ltr / ttb / btt。
<template>
<div class="demo-row">
<el-button @click="open('rtl')">从右向左</el-button>
<el-button @click="open('ltr')">从左向右</el-button>
<el-button @click="open('ttb')">从上向下</el-button>
<el-button @click="open('btt')">从下向上</el-button>
<el-drawer v-model="visible" :direction="direction" title="不同方向">
<p>当前方向:{{ direction }}</p>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Drawer as ElDrawer, Button as ElButton } from '@szhn/dh-design-pc'
type Dir = 'rtl' | 'ltr' | 'ttb' | 'btt'
const visible = ref(false)
const direction = ref<Dir>('rtl')
function open(d: Dir) {
direction.value = d
visible.value = true
}
</script>
<style scoped>
.demo-row {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
</style>不添加 Title
将 with-header 设置为 false 可以移除头部标题,适合自定义顶部的场景。
<template>
<div>
<el-button @click="drawer = true">打开无标题抽屉</el-button>
<el-drawer v-model="drawer" :with-header="false">
<p>不展示头部时,更适合自定义顶部结构。</p>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Drawer as ElDrawer, Button as ElButton } from '@szhn/dh-design-pc'
const drawer = ref(false)
</script>自定义内容
Drawer 内容区域可以放置任意内容,常用于展示表单、详情等。
<template>
<div>
<el-button type="primary" @click="drawer = true">创建新项目</el-button>
<el-drawer v-model="drawer" title="创建新项目">
<el-form :model="form" label-width="80px">
<el-form-item label="名称">
<el-input v-model="form.name" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="描述">
<el-input v-model="form.desc" type="textarea" rows="3" />
</el-form-item>
</el-form>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { Drawer as ElDrawer, Button as ElButton, Form as ElForm, FormItem as ElFormItem, Input as ElInput } from '@szhn/dh-design-pc'
const drawer = ref(false)
const form = reactive({ name: '', desc: '' })
</script>底部操作区
Drawer 默认展示标准底部操作区。右侧抽屉默认按钮靠左,顺序为“确认 / 取消”;其他方向默认按钮靠右,顺序为“取消 / 确认”。不需要底部时可将 show-footer 设为 false,需要特殊内容时可使用 footer 插槽覆盖默认按钮。
自定义头部
使用 header 具名插槽可以完全接管头部,搭配 title 属性可保留可访问性。
<template>
<div>
<el-button @click="drawer = true">打开自定义头部抽屉</el-button>
<el-drawer v-model="drawer" title="自定义头部">
<template #header="{ close, titleId, titleClass }">
<h4 :id="titleId" :class="titleClass" style="margin: 0;">🎨 自定义头部</h4>
<el-button size="small" @click="close">关闭</el-button>
</template>
<p>可以在头部里自由组织按钮、标签等内容。</p>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Drawer as ElDrawer, Button as ElButton } from '@szhn/dh-design-pc'
const drawer = ref(false)
</script>可调整尺寸 (2.11.0)
设置 resizable 为 true 后,用户可以拖拽抽屉边缘动态调整大小。
<template>
<div class="demo-row">
<el-button @click="open('rtl')">右侧抽屉</el-button>
<el-button @click="open('ltr')">左侧抽屉</el-button>
<el-button @click="open('ttb')">顶部抽屉</el-button>
</div>
<el-drawer v-model="drawer" :direction="direction" resizable title="可调整尺寸抽屉" size="40%">
试着拖拽抽屉边缘,调整当前抽屉的宽高尺寸。
</el-drawer>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Button as ElButton, Drawer as ElDrawer } from '@szhn/dh-design-pc'
const drawer = ref(false)
const direction = ref<'rtl' | 'ltr' | 'ttb' | 'btt'>('rtl')
function open(nextDirection: 'rtl' | 'ltr' | 'ttb' | 'btt') {
direction.value = nextDirection
drawer.value = true
}
</script>
<style scoped>
.demo-row {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
</style>嵌套抽屉
可以拥有多层嵌套的 Drawer,嵌套时需要对内部 Drawer 设置 append-to-body。
<template>
<div>
<el-button @click="outer = true">打开外层抽屉</el-button>
<el-drawer v-model="outer" title="外层抽屉" size="40%">
<p>这是外层抽屉的内容。</p>
<el-button type="primary" @click="inner = true">打开内层抽屉</el-button>
<el-drawer v-model="inner" title="内层抽屉" size="30%" append-to-body>
<p>嵌套抽屉需要 append-to-body 才能正确叠加。</p>
</el-drawer>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Drawer as ElDrawer, Button as ElButton } from '@szhn/dh-design-pc'
const outer = ref(false)
const inner = ref(false)
</script>模态层
将 modal 设为 false 可隐藏遮罩层;从 2.11.7 开始也可以配合 modal-penetrable 允许点击穿透。
<template>
<el-button plain @click="drawerVisible = true">
打开无遮罩抽屉
</el-button>
<el-drawer v-model="drawerVisible" :modal="false" modal-penetrable>
<span>这是一个关闭了遮罩层的 Drawer。</span>
</el-drawer>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Button as ElButton, Drawer as ElDrawer } from '@szhn/dh-design-pc'
const drawerVisible = ref(false)
</script>API
属性
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| model-value / v-model | 是否显示 Drawer | boolean | false |
| append-to-body | 是否插入至 body 元素 | boolean | false |
| lock-scroll | 显示时锁定 body 滚动 | boolean | true |
| before-close | 关闭前回调 | Function | — |
| close-on-click-modal | 点击遮罩关闭 | boolean | true |
| close-on-press-escape | ESC 关闭 | boolean | true |
| destroy-on-close | 关闭后销毁子元素 | boolean | false |
| modal | 是否需要遮罩层 | boolean | true |
modal-penetrable 2.11.7 | 遮罩是否允许穿透(需 modal=false) | boolean | false |
| direction | 打开方向 | rtl / ltr / ttb / btt | rtl |
| show-footer | 是否展示底部操作区 | boolean | true |
| footer-align | 底部按钮位置 | enum | auto |
| footer-order | 底部按钮顺序 | enum | auto |
| confirm-text | 确认按钮文案 | string | 确认 |
| cancel-text | 取消按钮文案 | string | 取消 |
| resizable | 允许调整大小 | boolean | false |
| show-close | 显示关闭按钮 | boolean | true |
| size | 尺寸 | number / string | 35% |
| title | 标题 | string | — |
| with-header | 是否显示头部 | boolean | true |
事件
| 事件名 | 说明 |
|---|---|
| confirm | 点击默认确认按钮时触发 |
| cancel | 点击默认取消按钮时触发 |
| open / opened | 打开 / 打开动画结束 |
| close / closed | 关闭 / 关闭动画结束 |
插槽
| 名称 | 说明 |
|---|---|
| default | Drawer 的内容 |
| header | Drawer 头部 |
| footer | Drawer 页脚 |
更多配置参见 Element Plus Drawer。
