Skip to content

BottomSheet

一个触摸驱动的底部弹出面板组件,内置惯性滚动、弹性吸附动画和滚动穿透处理。

Props

名称类型默认值说明
allowInertiaTransferbooleanfalse是否允许惯性动量在面板拖拽和内部列表滚动之间传递。false 时,惯性在两者边界处停止,防止列表"偷走"滑动。
maxVelocityLimitnumber30每帧最大速度限制(px),防止极速滑动产生过大位移。
minTranslateYnumber | nullnull折叠状态(最低点)吸附锚点,单位 px。默认为 window.innerHeight * 0.85
midTranslateYnumber | nullnull半展开状态吸附锚点。默认为 window.innerHeight * 0.6,组件挂载时的初始位置。
maxTranslateYnumber | nullnull完全展开状态(最高点)吸附锚点。默认为 window.innerHeight * 0.15

Events

事件名参数说明
load-more当内部列表滚动到底部 50px 范围内时触发,适用于无限滚动场景。

Slots

插槽名说明
default默认插槽,内容渲染在拖拽把手下方的列表容器中。

CSS 样式

组件使用 <style scoped>,以下是关键样式说明:

选择器说明
.bottom-sheetposition: absolute,铺满视口,白色背景,顶部圆角 24px,阴影,flex 纵向布局。
.drag-handle30px 高的拖拽把手区域,居中显示灰色圆角横条。
.list-containerflex: 1overflow: hidden(滚动由 JS 控制),底部 20vh 内边距。

由于滚动是通过 JavaScript 控制 scrollTop 实现的,样式中 overflow: hidden 是必须的,请勿覆盖。

基础示例

vue
<script setup>
import { BottomSheet } from '@wyatex/bottom-sheet'
import '@wyatex/bottom-sheet/dist/style.css'
</script>

<template>
  <div class="container">
    <BottomSheet>
      <div v-for="n in 30" :key="n" class="row">
        列表项 {{ n }}
      </div>
    </BottomSheet>
  </div>
</template>

<style scoped>
.container {
  position: fixed;
  inset: 0;
}
.row {
  padding: 16px 20px;
  border-bottom: 1px solid #f0f0f0;
}
</style>

无限滚动示例

vue
<script setup>
import { BottomSheet } from '@wyatex/bottom-sheet'
import { ref } from 'vue'
import '@wyatex/bottom-sheet/dist/style.css'

const items = ref(Array.from({ length: 20 }, (_, i) => i + 1))
const loading = ref(false)

function loadMore() {
  if (loading.value)
    return
  loading.value = true
  setTimeout(() => {
    const start = items.value.length
    for (let i = 0; i < 20; i++) {
      items.value.push(start + i + 1)
    }
    loading.value = false
  }, 500)
}
</script>

<template>
  <div class="container">
    <BottomSheet @load-more="loadMore">
      <div v-for="id in items" :key="id" class="row">
        📍 附近地点 {{ id }}
      </div>
      <div v-if="loading" class="loading">
        加载中...
      </div>
    </BottomSheet>
  </div>
</template>