Skip to content

Drawer 抽屉

有些时候,Dialog 组件并不满足我们的需求,比如你的表单很长,亦或是你需要临时展示一些文档,此时可以使用 Drawer。它拥有和 Dialog 几乎相同的 API,并在 UI 上带来不一样的体验。

ts
import { Drawer as ElDrawer } from '@szhn/dh-design-pc'

基础用法

通过 v-model 控制 Drawer 的显示与隐藏。默认情况下 Drawer 从右侧打开,占据 35% 的浏览器宽度,并展示标准底部操作区,可通过 directionsize 修改。

<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)

设置 resizabletrue 后,用户可以拖拽抽屉边缘动态调整大小。

<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是否显示 Drawerbooleanfalse
append-to-body是否插入至 body 元素booleanfalse
lock-scroll显示时锁定 body 滚动booleantrue
before-close关闭前回调Function
close-on-click-modal点击遮罩关闭booleantrue
close-on-press-escapeESC 关闭booleantrue
destroy-on-close关闭后销毁子元素booleanfalse
modal是否需要遮罩层booleantrue
modal-penetrable 2.11.7遮罩是否允许穿透(需 modal=falsebooleanfalse
direction打开方向rtl / ltr / ttb / bttrtl
show-footer是否展示底部操作区booleantrue
footer-align底部按钮位置enumauto
footer-order底部按钮顺序enumauto
confirm-text确认按钮文案string确认
cancel-text取消按钮文案string取消
resizable允许调整大小booleanfalse
show-close显示关闭按钮booleantrue
size尺寸number / string35%
title标题string
with-header是否显示头部booleantrue

事件

事件名说明
confirm点击默认确认按钮时触发
cancel点击默认取消按钮时触发
open / opened打开 / 打开动画结束
close / closed关闭 / 关闭动画结束

插槽

名称说明
defaultDrawer 的内容
headerDrawer 头部
footerDrawer 页脚

更多配置参见 Element Plus Drawer