uni-app 中 bottom-tabbar 随页面滑动显示/隐藏的原理是监听 scroll-view 的 @scroll 事件,通过对比 lastScrollTop 判断滚动方向,结合位移阈值动态设置底部栏 transform: translateY();不能依赖 onPageScroll,因其在微信小程序等非 H5 端不可靠。

uni-app 中 bottom-tabbar 随页面滑动显示/隐藏的原理
uni-app 没有内置「滑动显示底部栏」的能力,所谓“知乎式”效果,本质是监听 scroll-view 或页面滚动事件,根据 scrollTop 变化动态控制一个自定义底部容器的 transform: translateY() 或 opacity。关键不是“滑动触发”,而是“滚动方向 + 位移阈值”的组合判断。
为什么不能直接用 onPageScroll 监听页面滚动?
在非 H5 端(尤其是微信小程序和 App),onPageScroll 在非 scroll-view 包裹的普通页面中**不可靠或完全不触发**——这是最常踩的坑。知乎详情页实际结构是:整个内容区被 <scroll-view> 包裹,所有滚动行为都发生在该组件内,而非页面级。
-
onPageScroll只对 pages.json 中配置了"enablePullDownRefresh": true的原生页面生效,且仅在 H5 和部分 App 端稳定 - 微信小程序中,未包裹
scroll-view的页面滚动不会触发onPageScroll,真机静默失败 - 必须把内容区域显式用
<scroll-view scroll-y="true">包裹,并监听其@scroll事件
如何用 scroll-view 实现滑动底部栏动画
核心是把底部栏作为 scroll-view 的兄弟元素(非子元素),通过 ref 获取滚动偏移,再用 transform: translateY() 控制显示/隐藏。避免使用 v-if 或 opacity 切换,否则会打断手势连贯性。
知乎数据获取 - 极简设计,支持三级认证降级(Browser Profile → File Cookie → Fallback),确保数据可靠获取 Zhihu Data Fetcher - Minimalist design with three-level auth fallback (Browser Prof...
示例关键逻辑:
<scroll-view
class="content-scroll"
scroll-y
@scroll="onScroll"
:scroll-top="scrollTop"
ref="scrollView"
>
<!-- 文章内容 -->
</scroll-view>
<p><view class="bottom-bar" :style="{ transform: <code>translateY(${barTranslateY}px)</code> }">
<!-- 自定义 tab 按钮 -->
</view>
JS 部分需维护两个状态:
-
lastScrollTop:记录上一次滚动位置,用于判断方向(下滑隐藏 / 上滑显示) -
barTranslateY:当前底部栏 Y 偏移量,初始为0,下滑时设为60(假设高度 60px),上滑超过阈值(如 30px)再逐步归零 - 注意防抖:连续滚动中不要每帧都更新 DOM,建议节流至 16ms(约 60fps)
真机适配与容易忽略的细节
微信小程序和 App 端对 scroll-view 的 scrollTop 读取时机不一致,直接在 @scroll 回调里取 e.detail.scrollTop 可能滞后一帧。更稳的做法是用 this.$refs.scrollView.$getEl().scrollTop 主动获取(App 端兼容更好)。
- iOS 微信中,
scroll-view内嵌图片加载可能导致滚动卡顿,建议加lazy-load和占位图 - 底部栏必须用
position: fixed+bottom: 0,不能依赖 flex 或 margin 推挤,否则动画会跳 - 鸿蒙端
env(safe-area-inset-bottom)可能返回 0,需 fallback 到固定值(如padding-bottom: 34px) - 如果底部栏含凸起按钮,它的
z-index必须高于scroll-view,否则会被遮挡


















