onPageScroll不触发的主因是未在pages.json中配置"navigationStyle":"custom";H5需容器有高度和overflow,App/小程序端需避免scroll-view拦截原生滚动。

onPageScroll 不触发?先检查 navigationStyle 是否设为 custom
导航栏随滚动变化高度,本质是监听页面滚动并动态调整样式。但 onPageScroll 在 uni-app 中默认不生效——它只在启用了自定义导航栏的页面中才被调用。如果你写了函数却完全没日志输出,大概率是 pages.json 里漏了这句:
- 对应页面的
style下必须有"navigationStyle": "custom" - H5 端还需确保外层容器有明确高度(比如
uni-page-body { height: 100vh; })和overflow: auto - App 和小程序端要避免用
<scroll-view>包裹整个页面,否则会拦截原生滚动,onPageScroll就收不到事件
动态改高度不能直接操作原生导航栏
uni-app 的原生导航栏(navigationBarHeight)是只读的,无法通过 JS 动态修改其高度。所谓“改变高度”,实际是放弃原生栏,用 <view> 自绘一个固定定位的导航容器,再通过 onPageScroll 控制它的 height 或 transform: scaleY()。
- 推荐做法:用
position: fixed+top: 0定位自定义导航栏,初始高度设为 88rpx(含状态栏),滚动时逐步缩到 44rpx - 别试图用
uni.setNavigationBarColor改高度——这个 API 只控制背景色,且 H5/Android App 不支持 - 注意 iOS 状态栏高度(通常 20px)、Android 虚拟按键、H5 视口差异,统一用
uni.getSystemInfoSync().statusBarHeight获取
scrollTop 计算透明度 or 高度?阈值和插值方式要合理
滚动距离 scrollTop 是线性值,但人眼对“渐变”敏感度非线性。直接用 scrollTop / 100 做系数容易在起始段变化太突兀。
- 建议设置缓冲区间,例如:滚动前 60px 保持全高,60–160px 之间线性收缩,超过 160px 锁定最小高度
- 计算示例:
const alpha = Math.min(Math.max((scrollTop - 60) / 100, 0), 1),再用于height: `${88 - 44 * alpha}rpx` - 若同时做背景透明,别用
rgba(0,0,0,${alpha}),因为 alpha=0 时是纯黑底+文字不可读;应改为rgba(255,255,255,${1-alpha})或叠加半透明白色遮罩
各端渲染错位?statusBarHeight 必须显式参与布局
自定义导航栏在 iOS 上常被顶高、Android 文字下沉、H5 固定定位失效,根本原因是各端对状态栏的处理逻辑不同,而 uni-app 不自动帮你预留空间。
- 必须手动获取:
const { statusBarHeight } = uni.getSystemInfoSync(),存为响应式变量(如statusBarHeight = ref(0)) - 导航栏内层加状态栏占位:
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view> - 外层容器也要预留,否则内容会被遮挡:
<view class="page-content" :style="{ paddingTop: statusBarHeight + 88 + 'px' }"> - 别依赖 CSS 变量
--status-bar-height,它在某些 H5 浏览器或旧版 App 中未注入
最易忽略的一点:H5 端的 position: fixed 导航栏,在 Safari iOS 上可能因 viewport 缩放或地址栏隐藏/显示导致 top 偏移。上线前务必真机测试滚动过程中是否“跳动”。


















