Skip to content

Drawer 抽屉

屏幕边缘滑出的浮层面板。

代码演示

基础用法

基础抽屉,点击触发按钮抽屉从右滑出,点击遮罩区关闭。

vue
<template>
  <a-button type="primary" @click="showDrawer">Open</a-button>
  <a-drawer
    v-model:open="open"
    class="custom-class"
    root-class-name="root-class-name"
    :root-style="{ color: 'blue' }"
    style="color: red"
    title="Basic Drawer"
    placement="right"
    @after-open-change="afterOpenChange"
  >
    <p>Some contents...</p>
    <p>Some contents...</p>
    <p>Some contents...</p>
  </a-drawer>
</template>
<script setup>
import { ref } from 'vue';
const open = ref(false);
const afterOpenChange = bool => {
  console.log('open', bool);
};
const showDrawer = () => {
  open.value = true;
};
</script>

额外操作

在 Ant Design 规范中,操作按钮建议放在抽屉的右上角,可以使用 extra 属性来实现。

vue
<template>
  <a-radio-group v-model:value="placement" style="margin-right: 8px">
    <a-radio value="top">top</a-radio>
    <a-radio value="right">right</a-radio>
    <a-radio value="bottom">bottom</a-radio>
    <a-radio value="left">left</a-radio>
  </a-radio-group>
  <a-button type="primary" @click="showDrawer">Open</a-button>
  <a-drawer :width="500" title="Basic Drawer" :placement="placement" :open="open" @close="onClose">
    <template #extra>
      <a-button style="margin-right: 8px" @click="onClose">Cancel</a-button>
      <a-button type="primary" @click="onClose">Submit</a-button>
    </template>
    <p>Some contents...</p>
    <p>Some contents...</p>
    <p>Some contents...</p>
  </a-drawer>
</template>
<script setup>
import { ref } from 'vue';
const placement = ref('left');
const open = ref(false);
const showDrawer = () => {
  open.value = true;
};
const onClose = () => {
  open.value = false;
};
</script>

抽屉表单

在抽屉中使用表单。

vue
<template>
  <a-button type="primary" @click="showDrawer">
    <template #icon><PlusOutlined /></template>
    New account
  </a-button>
  <a-drawer
    title="Create a new account"
    :width="720"
    :open="open"
    :body-style="{ paddingBottom: '80px' }"
    :footer-style="{ textAlign: 'right' }"
    @close="onClose"
  >
    <a-form :model="form" :rules="rules" layout="vertical">
      <a-row :gutter="16">
        <a-col :span="12">
          <a-form-item label="Name" name="name">
            <a-input v-model:value="form.name" placeholder="Please enter user name" />
          </a-form-item>
        </a-col>
        <a-col :span="12">
          <a-form-item label="Url" name="url">
            <a-input
              v-model:value="form.url"
              style="width: 100%"
              addon-before="http://"
              addon-after=".com"
              placeholder="please enter url"
            />
          </a-form-item>
        </a-col>
      </a-row>
      <a-row :gutter="16">
        <a-col :span="12">
          <a-form-item label="Owner" name="owner">
            <a-select v-model:value="form.owner" placeholder="Please a-s an owner">
              <a-select-option value="xiao">Xiaoxiao Fu</a-select-option>
              <a-select-option value="mao">Maomao Zhou</a-select-option>
            </a-select>
          </a-form-item>
        </a-col>
        <a-col :span="12">
          <a-form-item label="Type" name="type">
            <a-select v-model:value="form.type" placeholder="Please choose the type">
              <a-select-option value="private">Private</a-select-option>
              <a-select-option value="public">Public</a-select-option>
            </a-select>
          </a-form-item>
        </a-col>
      </a-row>
      <a-row :gutter="16">
        <a-col :span="12">
          <a-form-item label="Approver" name="approver">
            <a-select v-model:value="form.approver" placeholder="Please choose the approver">
              <a-select-option value="jack">Jack Ma</a-select-option>
              <a-select-option value="tom">Tom Liu</a-select-option>
            </a-select>
          </a-form-item>
        </a-col>
        <a-col :span="12">
          <a-form-item label="DateTime" name="dateTime">
            <a-date-picker
              v-model:value="form.dateTime"
              style="width: 100%"
              :get-popup-container="trigger => trigger.parentElement"
            />
          </a-form-item>
        </a-col>
      </a-row>
      <a-row :gutter="16">
        <a-col :span="24">
          <a-form-item label="Description" name="description">
            <a-textarea
              v-model:value="form.description"
              :rows="4"
              placeholder="please enter url description"
            />
          </a-form-item>
        </a-col>
      </a-row>
    </a-form>
    <template #extra>
      <a-space>
        <a-button @click="onClose">Cancel</a-button>
        <a-button type="primary" @click="onClose">Submit</a-button>
      </a-space>
    </template>
  </a-drawer>
</template>
<script setup>
import { reactive, ref } from 'vue';
const form = reactive({
  name: '',
  url: '',
  owner: '',
  type: '',
  approver: '',
  dateTime: null,
  description: '',
});
const rules = {
  name: [
    {
      required: true,
      message: 'Please enter user name',
    },
  ],
  url: [
    {
      required: true,
      message: 'please enter url',
    },
  ],
  owner: [
    {
      required: true,
      message: 'Please select an owner',
    },
  ],
  type: [
    {
      required: true,
      message: 'Please choose the type',
    },
  ],
  approver: [
    {
      required: true,
      message: 'Please choose the approver',
    },
  ],
  dateTime: [
    {
      required: true,
      message: 'Please choose the dateTime',
      type: 'object',
    },
  ],
  description: [
    {
      required: true,
      message: 'Please enter url description',
    },
  ],
};
const open = ref(false);
const showDrawer = () => {
  open.value = true;
};
const onClose = () => {
  open.value = false;
};
</script>

渲染在当前 DOM

渲染在当前 dom 里。自定义容器,查看 getContainer。

Render in this
vue
<template>
  <div
    :style="{
      height: '200px',
      overflow: 'hidden',
      position: 'relative',
      border: '1px solid #ebedf0',
      borderRadius: '2px',
      padding: '48px',
      textAlign: 'center',
      background: '#fafafa',
    }"
  >
    Render in this
    <div style="margin-top: 16px">
      <a-button type="primary" @click="showDrawer">Open</a-button>
    </div>
    <a-drawer
      title="Basic Drawer"
      placement="right"
      :closable="false"
      :open="open"
      :get-container="false"
      :style="{ position: 'absolute' }"
      @close="onClose"
    >
      <p>Some contents...</p>
    </a-drawer>
  </div>
</template>
<script setup>
import { ref } from 'vue';
const open = ref(false);
const showDrawer = () => {
  open.value = true;
};
const onClose = () => {
  open.value = false;
};
</script>

多层抽屉

在抽屉内打开新的抽屉,用以解决多分支任务的复杂状况。

vue
<template>
  <a-button type="primary" @click="showDrawer">Open</a-button>
  <a-drawer
    v-model:open="open"
    title="Multi-level drawer"
    width="520"
    :closable="false"
    :footer-style="{ textAlign: 'right' }"
    @close="onClose"
  >
    <a-button type="primary" @click="showChildrenDrawer">Two-level drawer</a-button>
    <a-drawer v-model:open="childrenDrawer" title="Two-level Drawer" width="320" :closable="false">
      <a-button type="primary" @click="showChildrenDrawer">This is two-level drawer</a-button>
    </a-drawer>

    <template #footer>
      <a-button style="margin-right: 8px" @click="onClose">Cancel</a-button>
      <a-button type="primary" @click="onClose">Submit</a-button>
    </template>
  </a-drawer>
</template>
<script setup>
import { ref } from 'vue';
const open = ref(false);
const childrenDrawer = ref(false);
const showDrawer = () => {
  open.value = true;
};
const onClose = () => {
  open.value = false;
};
const showChildrenDrawer = () => {
  childrenDrawer.value = true;
};
</script>

API

参数说明类型默认值
autofocus抽屉展开后是否将焦点切换至其 Dom 节点booleantrue
bodyStyle可用于设置 Drawer 内容部分的样式CSSProperties-
classDrawer 容器外层 className 设置,如果需要设置最外层,请使用 rootClassNamestring-
closable是否显示左上角的关闭按钮booleantrue
closeIcon自定义关闭图标VNode | slot<CloseOutlined />
contentWrapperStyle可用于设置 Drawer 包裹内容部分的样式CSSProperties-
destroyOnClose关闭时销毁 Drawer 里的子元素booleanfalse
extra抽屉右上角的操作区域VNode | slot-
footer抽屉的页脚VNode | slot-
footerStyle抽屉页脚部件的样式CSSProperties-
forceRender预渲染 Drawer 内元素booleanfalse
getContainer指定 Drawer 挂载的节点,并在容器内展现 | () => HTMLElement | Selectors'body'
headerStyle用于设置 Drawer 头部的样式CSSProperties-
height高度, 在 placement 为 top 或 bottom 时使用string | number378
keyboard是否支持键盘 esc 关闭booleantrue
mask是否展示遮罩Booleantrue
maskClosable点击蒙层是否允许关闭booleantrue
maskStyle遮罩样式CSSProperties{}
placement抽屉的方向'top' | 'right' | 'bottom' | 'left''right'
push用于设置多层 Drawer 的推动行为boolean | {distance: string | number }{ distance: 180 }
rootClassName对话框外层容器的类名string-
rootStyle可用于设置 Drawer 最外层容器的样式,和 style 的区别是作用节点包括 maskCSSProperties-
size预设抽屉宽度(或高度),default 378px 和 large 736pxdefault | largedefault
style设计 Drawer 容器样式,如果你只需要设置内容部分请使用 bodyStyleCSSProperties-
title标题string | slot-
open(v-model)Drawer 是否可见boolean-
width宽度string | number378
zIndex设置 Drawer 的 z-indexNumber1000

事件

事件名称描述类型默认值
afterOpenChange切换抽屉时动画结束后的回调function(open)
close点击遮罩层或左上角叉或取消按钮的回调function(e)