Skip to content

Drawer 抽屉

像素风格的侧边面板,从屏幕边缘滑入。

名称分类说明类型默认值
showOverlay? 风格是否显示遮罩层booleantrue
size? 尺寸抽屉宽度string'300px'
v-model? 状态是否打开抽屉booleanfalse
placement? 行为抽屉弹出位置'left' | 'right''left'
lockScroll? 行为打开时是否锁定页面滚动booleantrue
closeOnClickOverlay? 行为点击遮罩层是否关闭booleantrue
closeOnEsc? 行为按 ESC 键是否关闭booleantrue
title? 内容抽屉标题string
update:modelValue? 事件打开/关闭状态改变时触发(value: boolean) => void
open? 事件抽屉打开时触发() => void
close? 事件抽屉关闭时触发() => void
default? 插槽主页面内容
sidebar? 插槽抽屉侧边栏内容
open? 暴露打开抽屉() => void
close? 暴露关闭抽屉() => void
toggle? 暴露切换抽屉打开/关闭() => void

基础用法

使用 v-model 控制抽屉的打开/关闭状态。内容放在 sidebar 插槽中。

<template>
  <div>
    <px-button @click="open = true">Open Drawer</px-button>
    <px-drawer v-model="open">
      <p>Main page content</p>
      <template #sidebar>
        <p>Sidebar content goes here.</p>
      </template>
    </px-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const open = ref(false);
</script>

弹出位置

使用 placement 设置抽屉从左侧或右侧滑入。

<template>
  <div class="demo-drawer">
    <px-button @click="leftOpen = true">Left (default)</px-button>
    <px-button @click="rightOpen = true">Right</px-button>
    <px-drawer v-model="leftOpen" placement="left">
      <template #sidebar>
        <p>Left sidebar content</p>
      </template>
    </px-drawer>
    <px-drawer v-model="rightOpen" placement="right">
      <template #sidebar>
        <p>Right sidebar content</p>
      </template>
    </px-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const leftOpen = ref(false);
const rightOpen = ref(false);
</script>

<style scoped>
.demo-drawer {
  display: flex;
  gap: 12px;
}
</style>

自定义尺寸

使用 size 设置抽屉宽度,接受任何 CSS 宽度值。

<template>
  <div class="demo-drawer">
    <px-button @click="open200 = true">200px</px-button>
    <px-button @click="open50 = true">50%</px-button>
    <px-drawer v-model="open200" size="200px">
      <template #sidebar>
        <p>Narrow drawer (200px)</p>
      </template>
    </px-drawer>
    <px-drawer v-model="open50" size="50%">
      <template #sidebar>
        <p>Wide drawer (50%)</p>
      </template>
    </px-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const open200 = ref(false);
const open50 = ref(false);
</script>

<style scoped>
.demo-drawer {
  display: flex;
  gap: 12px;
}
</style>

遮罩层

通过 show-overlayclose-on-click-overlay 控制背景遮罩层。

<template>
  <div class="demo-drawer">
    <px-button @click="withOverlay = true">With Overlay</px-button>
    <px-button @click="noOverlay = true">No Overlay</px-button>
    <px-button @click="noClose = true">No Close on Overlay</px-button>
    <px-drawer v-model="withOverlay">
      <template #sidebar>
        <p>Click overlay to close</p>
      </template>
    </px-drawer>
    <px-drawer v-model="noOverlay" :show-overlay="false">
      <template #sidebar>
        <p>No overlay background</p>
        <px-button @click="noOverlay = false">Close</px-button>
      </template>
    </px-drawer>
    <px-drawer v-model="noClose" :close-on-click-overlay="false">
      <template #sidebar>
        <p>Overlay click won't close</p>
        <px-button @click="noClose = false">Close</px-button>
      </template>
    </px-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const withOverlay = ref(false);
const noOverlay = ref(false);
const noClose = ref(false);
</script>

<style scoped>
.demo-drawer {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}
</style>

标题

使用 title 属性渲染带有像素虚线分隔符的标题栏。

<template>
  <div>
    <px-button @click="open = true">Drawer with Title</px-button>
    <px-drawer v-model="open" title="Settings">
      <template #sidebar>
        <p>The header shows a pixel-dashed divider below the title.</p>
      </template>
    </px-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const open = ref(false);
</script>

禁用 ESC 关闭

设置 close-on-escfalse 以禁止按 ESC 键关闭抽屉。

<template>
  <div>
    <px-button @click="open = true">Escape Disabled</px-button>
    <px-drawer v-model="open" :close-on-esc="false">
      <template #sidebar>
        <p>Press Escape — nothing happens.</p>
        <px-button @click="open = false">Close Manually</px-button>
      </template>
    </px-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const open = ref(false);
</script>