Skip to content
API 风格:

Drawer 抽屜 ​

側滑面板,從螢幕邊緣滑入,適合比 Dialog 更貼邊的臨時操作(詳情、篩選、精靈步驟)。與 Dialog 一致採用 role="dialog" + aria-modal="true",焦點圈在面板內,Esc 與遮罩點選均可關閉。

基礎用法 ​

右側抽屜
vue
<template>
  <LhButton @click="basic = true">打开抽屉</LhButton>
  <LhDrawer v-model="basic" title="订单详情">
    <p>这里放置抽屉主体内容。</p>
  </LhDrawer>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const basic = ref(false)
</script>
vue
<script>
export default {
  data() {
    return { basic: false }
  },
}
</script>

<template>
  <LhButton @click="basic = true">打开抽屉</LhButton>
  <LhDrawer v-model="basic" title="订单详情">
    <p>这里放置抽屉主体内容。</p>
  </LhDrawer>
</template>

四個方向 ​

right / left / top / bottom
vue
<script setup lang="ts">
import { ref } from 'vue'
const dirVisible = ref(false)
const direction = ref<'right' | 'left' | 'top' | 'bottom'>('right')
const size = ref('40%')
function openDir(d: 'right' | 'left' | 'top' | 'bottom') {
  direction.value = d
  dirVisible.value = true
}
</script>

<template>
  <!-- 打開右側抽屜 -->
  <LhButton @click="openDir('right')">right</LhButton>
  <!-- 打開左側抽屜 -->
  <LhButton @click="openDir('left')">left</LhButton>
  <!-- 打開頂部抽屜 -->
  <LhButton @click="openDir('top')">top</LhButton>
  <!-- 打開底部抽屜 -->
  <LhButton @click="openDir('bottom')">bottom</LhButton>
  <!-- 依指定方向滑出 -->
  <LhDrawer v-model="dirVisible" :title="`${direction} 抽屉`" :direction="direction" :size="size">
    <p>当前方向:{{ direction }}</p>
  </LhDrawer>
</template>
vue
<script>
export default {
  data() {
    return { dirVisible: false, direction: 'right', size: '40%' }
  },
  methods: {
    openDir(d) {
      this.direction = d
      this.dirVisible = true
    },
  },
}
</script>

<template>
  <!-- 打開右側抽屜 -->
  <LhButton @click="openDir('right')">right</LhButton>
  <!-- 打開左側抽屜 -->
  <LhButton @click="openDir('left')">left</LhButton>
  <!-- 打開頂部抽屜 -->
  <LhButton @click="openDir('top')">top</LhButton>
  <!-- 打開底部抽屜 -->
  <LhButton @click="openDir('bottom')">bottom</LhButton>
  <!-- 依指定方向滑出 -->
  <LhDrawer v-model="dirVisible" :title="`${direction} 抽屉`" :direction="direction" :size="size">
    <p>当前方向:{{ direction }}</p>
  </LhDrawer>
</template>

自訂尺寸與底部 ​

size 與 footer 插槽
vue
<script setup lang="ts">
import { ref } from 'vue'

const sized = ref(false)
</script>

<template>
  <!-- 打開 480px 寬抽屜 -->
  <LhButton @click="sized = true">480px 宽抽屉</LhButton>
  <!-- 固定尺寸的抽屜,底部為操作區 -->
  <LhDrawer v-model="sized" title="筛选条件" :size="480">
    <LhInput placeholder="按名称筛选" />
    <LhInput placeholder="按标签筛选" />
    <template #footer>
      <LhButton @click="sized = false">取消</LhButton>
      <LhButton type="primary" @click="sized = false">应用筛选</LhButton>
    </template>
  </LhDrawer>
</template>
vue
<script>
export default {
  data() {
    return { sized: false }
  },
}
</script>

<template>
  <!-- 打開 480px 寬抽屜 -->
  <LhButton @click="sized = true">480px 宽抽屉</LhButton>
  <!-- 固定尺寸的抽屜,底部為操作區 -->
  <LhDrawer v-model="sized" title="筛选条件" :size="480">
    <LhInput placeholder="按名称筛选" />
    <LhInput placeholder="按标签筛选" />
    <template #footer>
      <LhButton @click="sized = false">取消</LhButton>
      <LhButton type="primary" @click="sized = false">应用筛选</LhButton>
    </template>
  </LhDrawer>
</template>

size 傳數字為 px,傳字串支援百分比(如 '40%')。左右方向作用於寬度,上下方向作用於高度。

行為開關 ​

mask-closable 禁止點遮罩關閉、show-close 隱藏右上角關閉按鈕、close-on-esc 停用 Esc 關閉、lock-scroll 開啟時不鎖定頁面捲動、teleport-target 指定掛載容器。

行為開關
vue
<script setup lang="ts">
import { ref } from 'vue'

const adv1 = ref(false)
const adv2 = ref(false)
const adv3 = ref(false)
</script>

<template>
  <!-- 打開「僅按鈕關閉」抽屜 -->
  <LhButton @click="adv1 = true">仅按钮关闭</LhButton>
  <!-- 打開「不鎖定捲動」抽屜 -->
  <LhButton @click="adv2 = true">不锁定滚动</LhButton>
  <!-- 遮罩點選與 Esc 均不關閉 -->
  <LhDrawer
    v-model="adv1"
    title="仅按钮关闭"
    :mask-closable="false"
    :show-close="false"
    :close-on-esc="false"
  >
    <p>遮罩点击与 Esc 均不关闭,只能通过按钮关闭。</p>
    <template #footer>
      <LhButton type="primary" @click="adv1 = false">关闭</LhButton>
    </template>
  </LhDrawer>
  <!-- 開啟時頁面仍可捲動 -->
  <LhDrawer v-model="adv2" title="不锁定滚动" :lock-scroll="false">
    <p>抽屉打开时页面仍可滚动。</p>
  </LhDrawer>
  <!-- 掛載到指定容器 -->
  <LhDrawer v-model="adv3" title="指定挂载容器" teleport-target="#drawer-host">
    <p>面板被传送到 id 为 drawer-host 的容器内。</p>
  </LhDrawer>
</template>
vue
<script>
export default {
  data() {
    return { adv1: false, adv2: false, adv3: false }
  },
}
</script>

<template>
  <!-- 打開「僅按鈕關閉」抽屜 -->
  <LhButton @click="adv1 = true">仅按钮关闭</LhButton>
  <!-- 打開「不鎖定捲動」抽屜 -->
  <LhButton @click="adv2 = true">不锁定滚动</LhButton>
  <!-- 遮罩點選與 Esc 均不關閉 -->
  <LhDrawer
    v-model="adv1"
    title="仅按钮关闭"
    :mask-closable="false"
    :show-close="false"
    :close-on-esc="false"
  >
    <p>遮罩点击与 Esc 均不关闭,只能通过按钮关闭。</p>
    <template #footer>
      <LhButton type="primary" @click="adv1 = false">关闭</LhButton>
    </template>
  </LhDrawer>
  <!-- 開啟時頁面仍可捲動 -->
  <LhDrawer v-model="adv2" title="不锁定滚动" :lock-scroll="false">
    <p>抽屉打开时页面仍可滚动。</p>
  </LhDrawer>
  <!-- 掛載到指定容器 -->
  <LhDrawer v-model="adv3" title="指定挂载容器" teleport-target="#drawer-host">
    <p>面板被传送到 id 为 drawer-host 的容器内。</p>
  </LhDrawer>
</template>

Drawer API ​

Props ​

屬性說明類型預設值
modelValue是否顯示(v-model)boolean—
title標題(也可用 header 插槽)string—
direction方向"right" | "left" | "top" | "bottom"'right'
size尺寸:數字為 px,字串支援百分比string | number'30%'
maskClosable點選遮罩是否關閉booleantrue
showClose是否顯示關閉按鈕booleantrue
teleportTargetTeleport 目標(選擇器或元素,預設 body)string | HTMLElement'body'
lockScroll是否鎖定頁面捲動booleantrue
closeOnEsc是否回應 Esc 關閉booleantrue
themeVars元件級主題變數,覆寫 ConfigProvider 設定{ [x: string]: string; }—
bgPattern元件級背景花紋,覆寫 ConfigProvider 設定string—
sxsx 快速版面配置屬性(作用於面板)LhSxProps—

Events ​

事件說明參數
update:model-value顯隱變化(value: boolean)
open開啟後觸發—
close關閉後觸發—

Slots ​

插槽說明
default主體內容
header自訂頭部(含標題區)
footer自訂底部操作區

Methods ​

方法說明
open程式化開啟
close程式化關閉

無障礙 ​

  • role="dialog" + aria-modal="true";有標題時透過 aria-labelledby 關聯,無標題時用語言包 drawer.title 作 aria-label 兜底
  • 開啟時焦點移入面板首個可聚焦元素,Tab 在面板內循環,關閉後歸還觸發器焦點
  • Esc 關閉(可由 close-on-esc 關閉該行為);遮罩為裝飾性(aria-hidden)
  • 關閉按鈕為真實 <button>,aria-label 取語言包 drawer.close
  • 進出滑動動效在 prefers-reduced-motion 下降級為純淡入淡出

類型定義 ​

本元件對外匯出的 TypeScript 類型結構如下(自動提取自 packages/components/drawer/src/types.ts 與 @lh-ui/share/core/* 原始碼,點選各條目展開檢視完整定義;屬性說明見上方 Props 表):

LhDrawerProps
ts
/**
 * Drawer 元件 Props
 */
export interface LhDrawerProps {
  /** 是否顯示(v-model) */
  modelValue?: boolean
  /** 標題 */
  title?: string
  /** 方向 */
  direction?: LhDrawerDirection
  /** 尺寸:數字為 px,字串支援百分比 */
  size?: string | number
  /** 點選遮罩是否關閉 */
  maskClosable?: boolean
  /** 是否顯示關閉按鈕 */
  showClose?: boolean
  /** Teleport 目標(選擇器或元素,預設 body) */
  teleportTarget?: string | HTMLElement
  /** 是否鎖定頁面捲動 */
  lockScroll?: boolean
  /** 是否回應 Esc 關閉 */
  closeOnEsc?: boolean
  /** 元件級主題變數,覆寫 ConfigProvider 設定 */
  themeVars?: Record<string, string>
  /** 元件級背景花紋,覆寫 ConfigProvider 設定 */
  bgPattern?: string
  /** sx 快速版面配置屬性(作用於面板) */
  sx?: LhSxProps
}
LhDrawerDirection (來自 @lh-ui/share/core/drawer (logic.ts))
ts
/**
 * Drawer 純函式邏輯(無框架依賴)
 */

/** 抽屜方向 */
export type LhDrawerDirection = 'right' | 'left' | 'top' | 'bottom'