Skip to content

FmDrawer 抽屉组件

侧滑抽屉组件,支持从四个方向弹出,内置头部、内容区和底部操作区。

基础用法

vue
<script setup lang="ts">
const open = ref(false)
</script>

<template>
  <FmButton @click="open = true">打开抽屉</FmButton>
  <FmDrawer v-model="open" title="抽屉标题">
    <div>抽屉内容</div>
  </FmDrawer>
</template>

Props

属性类型默认值说明
idstring-抽屉唯一标识
modelValuebooleanfalse是否打开抽屉
zIndexnumber2000层级
side'top' | 'bottom' | 'left' | 'right''right'弹出方向
titlestring | () => string-标题
descriptionstring | () => string-描述文字
loadingbooleanfalse是否显示加载状态
closablebooleantrue是否显示关闭按钮
centeredbooleanfalse是否居中显示
borderedbooleantrue是否有边框分割线
overlaybooleantrue是否显示遮罩
overlayBlurbooleanfalse遮罩是否模糊
showConfirmButtonbooleantrue是否显示确定按钮
showCancelButtonbooleanfalse是否显示取消按钮
confirmButtonTextstring | () => string'确定'确定按钮文字
cancelButtonTextstring | () => string'取消'取消按钮文字
confirmButtonDisabledbooleanfalse确定按钮是否禁用
confirmButtonLoadingbooleanfalse确定按钮加载状态
beforeClose(action, done) => void-关闭前回调
headerbooleantrue是否显示头部
footerbooleantrue是否显示底部
closeOnClickOverlaybooleantrue点击遮罩是否关闭
closeOnPressEscapebooleantrue按 ESC 是否关闭
destroyOnClosebooleantrue关闭时销毁内容
openAutoFocusbooleanfalse打开时自动聚焦
contentClassHTMLAttributes['class']-内容区 CSS 类
headerClassHTMLAttributes['class']-头部 CSS 类
footerClassHTMLAttributes['class']-底部 CSS 类

Slots

名称说明
header自定义头部内容
default抽屉主体内容
footer自定义底部内容

Events

事件名说明
update:modelValue打开状态变化时触发
open打开时触发
opened打开动画完成后触发
close关闭时触发
closed关闭动画完成后触发
confirm点击确定按钮时触发
cancel点击取消按钮时触发

Exposed Methods

示例

基础抽屉

vue
<script setup lang="ts">
const open = ref(false)
</script>

<template>
  <FmButton @click="open = true">打开抽屉</FmButton>
  <FmDrawer v-model="open" title="抽屉标题" description="抽屉描述">
    <div>这是抽屉内容</div>
  </FmDrawer>
</template>

不同弹出方向

vue
<script setup lang="ts">
const drawers = reactive({
  top: false,
  bottom: false,
  left: false,
  right: false,
})
</script>

<template>
  <div class="flex gap-2">
    <FmButton @click="drawers.top = true">上方抽屉</FmButton>
    <FmButton @click="drawers.bottom = true">下方抽屉</FmButton>
    <FmButton @click="drawers.left = true">左侧抽屉</FmButton>
    <FmButton @click="drawers.right = true">右侧抽屉</FmButton>
  </div>
  
  <FmDrawer v-model="drawers.top" side="top" title="上方抽屉">内容</FmDrawer>
  <FmDrawer v-model="drawers.bottom" side="bottom" title="下方抽屉">内容</FmDrawer>
  <FmDrawer v-model="drawers.left" side="left" title="左侧抽屉">内容</FmDrawer>
  <FmDrawer v-model="drawers.right" side="right" title="右侧抽屉">内容</FmDrawer>
</template>

带底部按钮

vue
<script setup lang="ts">
const open = ref(false)

function handleConfirm() {
  console.log('确认操作')
  open.value = false
}

function handleCancel() {
  console.log('取消操作')
  open.value = false
}
</script>

<template>
  <FmButton @click="open = true">打开抽屉</FmButton>
  <FmDrawer
    v-model="open"
    title="确认操作"
    show-cancel-button
    @confirm="handleConfirm"
    @cancel="handleCancel"
  >
    <div>请确认是否继续?</div>
  </FmDrawer>
</template>

关闭前确认

vue
<script setup lang="ts">
import { useFmModal } from '@fantastic-mobile/components'

const open = ref(false)

function handleBeforeClose(action: 'confirm' | 'cancel' | 'close', done: () => void) {
  if (action === 'close') {
    useFmModal().confirm({
      title: '提示',
      content: '确定要关闭吗?未保存的内容将丢失。',
      onConfirm: () => done(),
    })
  }
  else {
    done()
  }
}
</script>

<template>
  <FmDrawer v-model="open" title="编辑" :before-close="handleBeforeClose">
    <form>
      <FmInput placeholder="请输入..." />
    </form>
  </FmDrawer>
</template>

加载状态

vue
<script setup lang="ts">
const open = ref(false)
const loading = ref(false)

function handleSubmit() {
  loading.value = true
  setTimeout(() => {
    loading.value = false
    open.value = false
  }, 2000)
}
</script>

<template>
  <FmDrawer v-model="open" title="提交表单" :loading="loading" :confirm-button-loading="loading" @confirm="handleSubmit">
    <form class="flex flex-col gap-4">
      <FmInput placeholder="输入内容" />
    </form>
  </FmDrawer>
</template>

自定义头部和底部

vue
<template>
  <FmDrawer v-model="open">
    <template #header>
      <div class="flex-between">
        <span class="font-bold">自定义标题</span>
        <FmIcon name="i-lucide:info" />
      </div>
    </template>
    <div>抽屉内容</div>
    <template #footer>
      <div class="flex gap-2">
        <FmButton variant="outline">取消</FmButton>
        <FmButton>保存</FmButton>
      </div>
    </template>
  </FmDrawer>
</template>

调整抽屉宽度

vue
<template>
  <FmDrawer v-model="open" title="大抽屉" content-class="sm:max-w-2xl">
    <div>这是一个较宽的抽屉</div>
  </FmDrawer>
</template>

居中显示

vue
<template>
  <FmDrawer v-model="open" title="居中抽屉" centered show-cancel-button>
    <div class="text-center">
      <p>这是一个居中的抽屉</p>
      <p>按钮也会居中对齐</p>
    </div>
  </FmDrawer>
</template>

函数式调用

vue
<script setup lang="ts">
const drawer = useFmDrawer()

function openDrawer() {
  drawer.create({
    title: '提示',
    content: '这是一个抽屉',
    onConfirm: () => {
      console.log('确认操作')
    },
  }).open()
}
</script>

注意事项

  1. v-model 绑定:使用 v-model 控制抽屉打开状态
  2. 方向选择side 支持 topbottomleftright 四个方向
  3. 关闭回调beforeClose 接收 actionconfirm/cancel/close)和 done 函数
  4. 加载状态loading 会显示遮罩层,confirmButtonLoading 只影响按钮
  5. 动画事件openedclosed 在动画完成后触发
  6. 默认关闭行为:点击确定/取消按钮会自动关闭抽屉,如需阻止请在 beforeClose 中处理

典型使用场景

  • 表单编辑
  • 详情展示
  • 过滤筛选条件
  • 配置设置
  • 确认对话框(使用 show-cancel-button)