结论:uni-app 无法用原生 tabbar 实现滚动方向联动显隐,因其独立于页面生命周期、不响应滚动事件且不支持条件显隐;必须用 scroll-view + 自定义底部栏或 onpagescroll + 自定义组件实现。

直接说结论:uni-app 里没法用原生 tabBar 实现“随滚动方向显示/隐藏底部栏”,必须用自定义组件 + scroll-view 或页面级 onPageScroll 手动控制显隐逻辑。
为什么原生 tabBar 不支持滚动联动
uni-app 的 tabBar 是 pages.json 配置的原生导航栏,生命周期独立于页面 JS,不响应 onPageScroll、不监听滚动事件,也不能动态修改 show/hide 状态。哪怕你调用 uni.hideTabBar() 或 uni.showTabBar(),也只支持整页开关,无法做“向上滑隐藏、向下滑显示”这种条件判断。
用 scroll-view 包裹内容 + 自定义底部栏组件
这是最可控、兼容性最好的方案,尤其适合知乎日报这类详情页(HTML 内容需解析渲染,必须用 scroll-view 才能保证 iOS 安卓滚动一致性)。
播客文章生成器。将音频文字稿、节目链接、摘要笔记转化为结构清晰、适合发布的图文文章。支持多种输出风格(深度解析、精华摘要、对话体重构、社交媒体切片)和多种输出格式(Markdown、微信公众号、知乎、企业内刊)。触发词:播客文章、播客转文章、podcast to article、podcast article
- 在页面 template 中用
<scroll-view scroll-y="true"></scroll-view>包住正文,禁用页面原生滚动(disableScroll: true在 pages.json 中设) - 底部栏用绝对定位:
position: fixed; bottom: 0; left: 0; right: 0; z-index: 999; - 用 data 存一个
isBottomBarVisible: true,在onScroll里根据event.detail.scrollTop和上一次 scrollTop 做差值判断滚动方向 - 加防抖:连续滚动时避免频繁 setState,建议用
setTimeout清除上次定时器,延迟 150ms 再执行显隐 - 注意 iOS 上
scroll-view的scroll-top可能为负值(下拉刷新导致),判断前先Math.max(0, scrollTop)
用页面级 onPageScroll + 自定义 tabBar 组件
如果不想改结构、坚持用页面原生滚动(即不用 scroll-view),就得放弃原生 tabBar,自己写一个浮在底部的组件,并靠 onPageScroll 控制。
- 先在 pages.json 中移除
tabBar配置,调用uni.hideTabBar({ fail: () => {} })确保它不出现 - 自定义组件(如
custom-bottom-bar.vue)用position: fixed+z-index覆盖到底部 - 在页面
onPageScroll生命周期里获取scrollTop,记录上一次值,比较差值符号决定显隐 - 关键点:微信小程序中
onPageScroll在页面滚动时高频触发,但真机上实际频率受限,iOS 尤其卡顿,所以显隐动画建议用transform: translateY()而非v-show切换,减少重排 - 安卓和 iOS 表现不一致:iOS 滚动惯性大,
scrollTop变化更平滑;安卓可能突变,建议差值阈值设为 10px 而非 1px
容易被忽略的细节
滚动方向判断不是简单比大小——用户快速上划再停住,scrollTop 可能还在惯性变化;手指松开后还会继续滚动几十毫秒。真正健壮的做法是:记录 lastScrollTop 和 lastTimestamp,只在时间间隔 > 50ms 且差值 > 8px 时才更新状态。另外,底部栏如果有输入框或按钮,要确保 pointer-events: auto,否则 fixed 定位后可能点不到。









