抽屉 Drawer
屏幕边缘滑出的浮层面板,承载查看详情、编辑表单等内容,不中断当前操作流。
基础用法
通过 placement 属性设置抽屉弹出方向,支持 right(默认)、left、up、down 四个方向。
vue
<template>
<bp-space :size="16">
<bp-button @click="handleOpen('right')">右侧弹出</bp-button>
<bp-button @click="handleOpen('left')">左侧弹出</bp-button>
</bp-space>
<bp-drawer v-model="show" :placement title="基础抽屉">
<p>这是一个基础的抽屉组件。</p>
</bp-drawer>
</template>
<script setup lang="ts">
import { ref } from "vue";
const show = ref(false);
const placement = ref("right");
const handleOpen = (p: string) => {
placement.value = p;
show.value = true;
};
</script>弹出方向
分别从四个方向打开抽屉,左右方向通过 width 控制宽度,上下方向通过 height 控制高度。
vue
<template>
<bp-space :size="16">
<bp-button @click="handleOpen('right')">右侧弹出</bp-button>
<bp-button @click="handleOpen('left')">左侧弹出</bp-button>
<bp-button @click="handleOpen('up')">上方弹出</bp-button>
<bp-button @click="handleOpen('down')">下方弹出</bp-button>
</bp-space>
<bp-drawer v-model="show" :placement title="弹出方向">
<p>当前弹出方向:{{ placement }}</p>
</bp-drawer>
</template>
<script setup lang="ts">
import { ref } from "vue";
const show = ref(false);
const placement = ref("right");
const handleOpen = (p: string) => {
placement.value = p;
show.value = true;
};
</script>自定义插槽
使用 header、footer 和默认插槽自定义抽屉的头部、底部和内容区域。
vue
<template>
<bp-space :size="16">
<bp-button @click="showCustom = true">自定义内容</bp-button>
<bp-button @click="showHeader = true">自定义头部</bp-button>
<bp-button @click="showFooter = true">自定义底部</bp-button>
</bp-space>
<bp-drawer v-model="showCustom" title="用户详情">
<div class="custom-content">
<p><strong>姓名:</strong>张三</p>
<p><strong>邮箱:</strong>zhangsan@example.com</p>
<p><strong>部门:</strong>技术部</p>
</div>
</bp-drawer>
<bp-drawer v-model="showHeader" title="自定义头部">
<template #header>
<div class="custom-header">
<IconStarFill size="18" style="color: #f7ba2a" />
<span>自定义标题区域</span>
</div>
</template>
<p>头部区域使用了自定义插槽。</p>
</bp-drawer>
<bp-drawer v-model="showFooter" title="自定义底部">
<p>底部使用了自定义插槽。</p>
<template #footer>
<bp-button type="secondary" @click="showFooter = false">关闭</bp-button>
<bp-button status="danger" @click="showFooter = false">删除</bp-button>
</template>
</bp-drawer>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { IconStarFill } from "birdpaper-icon";
const showCustom = ref(false);
const showHeader = ref(false);
const showFooter = ref(false);
</script>
<style lang="scss" scoped>
.custom-content {
p {
line-height: 2.2;
border-bottom: 1px solid #f0f0f0;
}
}
.custom-header {
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
}
</style>异步确认
通过 on-before-ok 回调实现异步确认,确认按钮会自动进入 loading 状态。返回 true 关闭抽屉,返回 false 则保持打开。
vue
<template>
<bp-button @click="show = true">异步确认</bp-button>
<bp-drawer v-model="show" title="提交确认" :on-before-ok="handleBeforeOk">
<p>点击确认后将执行异步操作,确认按钮会自动进入 loading 状态。</p>
</bp-drawer>
</template>
<script setup lang="ts">
import { ref } from "vue";
const show = ref(false);
const handleBeforeOk = async () => {
await new Promise((resolve) => setTimeout(resolve, 2000));
return true;
};
</script>Drawer 属性
| v-model | 抽屉是否可见 | Boolean | - | - |
| title | 抽屉标题 | String | 标题 | - |
| width | 抽屉宽度(left/right 方向生效) | String | 360px | - |
| height | 抽屉高度(up/down 方向生效) | String | 360px | - |
| placement | 抽屉弹出方向 | String | right | - |
| hide-footer | 是否隐藏底部区域 | Boolean | - | - |
| hide-close | 是否隐藏关闭按钮 | Boolean | - | - |
| border | 是否显示边框 | Boolean | - | - |
| mask-closable | 点击遮罩是否关闭抽屉 | Boolean | true | - |
| ok-text | 确认按钮文字 | String | 确认 | - |
| cancel-text | 取消按钮文字 | String | 取消 | - |
| on-before-ok | 确认前的异步回调,返回 true 关闭抽屉,返回 false 保持打开。按钮自动进入 loading 状态 | Function | - | - |
Drawer 事件
| cancel | 点击取消或关闭按钮时触发 | - | - |
| confirm | 点击确认按钮后触发 | - | - |
Drawer 插槽
| default | 抽屉内容区域 | - | - |
| header | 自定义头部区域 | - | - |
| footer | 自定义底部按钮区域 | - | - |