onpagescroll 拿不到 scrolltop 是因页面禁用了原生滚动,需检查 pages.json 中是否配置了 "disablescroll": true,或存在自定义 tabbar、subnvue、router-view 包裹导致事件失效。

onPageScroll 拿不到 scrollTop?检查 pages.json 是否禁用了滚动
商品详情页要实现导航栏随滚动平滑切换,第一步必须确保能拿到真实的滚动距离。很多人写完 onPageScroll 回调却始终收不到数据,根本原因是页面被强制禁用了原生滚动。
检查 pages.json 中对应页面的配置项:
- 确认没写
"disableScroll": true—— 这会直接屏蔽所有滚动事件 - 如果用了自定义 TabBar 或 subNVue 容器,
onPageScroll默认不触发,得换用scroll-view+bindscroll - H5 端若套了 router-view 或 layout 包裹层,需确保根节点是 page 实例,否则事件监听失效
导航栏吸顶 + 平滑切换:别用 fixed,用 transform + will-change
直接写 position: fixed 在安卓低端机上容易抖动、回弹错位,尤其搭配视差元素时更明显。淘宝式效果的核心是“视觉锚定+位移补偿”,不是纯 CSS 定位。
推荐做法:
- 导航栏保持
position: relative,用transform: translateY()控制显隐和过渡 - 位移值由
scrollTop计算得出,但要做限幅:比如Math.min(scrollTop, 120)防止过度偏移 - 加
will-change: transform和transform: translateZ(0)触发硬件加速,避免安卓闪屏 - 过渡用
transition: transform 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94),比 linear 更跟手
导航高亮同步:用节流 + 区间判断,别硬比 scrollTop === 某个值
常见错误是写一堆 if (scrollTop >= 800 && scrollTop ,结果滑动快时高亮跳变、卡顿、来回闪烁。
真正稳定的逻辑是:
- 预先记录每个内容区块的
offsetTop(用uni.createSelectorQuery()在onReady获取) - 滚动时对
scrollTop + window.innerHeight * 0.3做区间匹配(加 30% 视口偏移,提前激活) - 用 30ms 节流包裹判断逻辑,避免频繁重计算 —— 直接用
throttle(fn, 30)就行,别自己写 setTimeout 套壳 - 高亮切换用
class控制,不要 inline style,否则 uni-app 的 diff 会丢样式
视差层与导航联动:背景图位移 ≠ 滚动距离 × 系数
把商品头图设成 transform: translateY(scrollTop * 0.3) 看起来很直观,但实际一滑就飘、松散、失去焦点感 —— 淘宝的视差是“有阻尼的跟随”,不是线性映射。
更合理的做法:
- 用
scrollTop做输入,经easeOutCubic缓动函数映射为位移值(例如y = 1 - Math.pow(1 - t, 3)) - 限制最大位移在 ±40px 内,避免视觉失重
- 导航栏文字 opacity 和 background-color 同步渐变,用同一缓动曲线,强化层次感
- iOS 真机上若出现模糊,给视差容器加
-webkit-backface-visibility: hidden
复杂点不在代码量,在于每个区块的 offset 计算时机和缓动节奏是否一致 —— 差 50ms 就会觉得“不同步”。










