onpagescroll是唯一可靠的页面级滚动监听入口,仅在页面根容器可滚动时触发,参数e仅有scrolltop和scrollleft字段;混用页面滚动与scroll-view时二者互斥,需按来源正确调用uni.pagescrollto或scrollto。
直接用 onpagescroll,别碰 window.pageyoffset 或 document.documentelement.scrolltop —— 这俩在小程序和 app 端根本不存在,h5 虽能跑但一打包就失效。
onPageScroll 是唯一可靠的页面级滚动监听入口
它不是事件,是页面生命周期函数,只在页面根容器可滚动时触发(比如内容超出一屏、pages.json 没设 "disableScroll": true)。参数 e 是个对象,只有 e.scrollTop 和 e.scrollLeft 两个字段,单位 px,恒为正。
- 微信小程序、App、H5 都支持;支付宝小程序不支持,得降级处理(比如用
<scroll-view></scroll-view>包一层) - 必须写在页面级 Vue 实例上,组件里定义无效
-
onPageScroll不会因<scroll-view></scroll-view>滚动而触发 —— 它只管“整个页面”的滚动 - 真机调试时,安卓机型存在节流(约 16ms~60ms 一次),别依赖高频精确值
页面用了 scroll-view,onPageScroll 就失效
一旦你把内容包进 <scroll-view scroll-y></scroll-view>,页面级滚动容器就消失了,onPageScroll 彻底失灵。此时必须改用 @scroll 事件,取值方式也不同:
- 监听的是
e.detail.scrollTop,不是e.scrollTop - 需给
<scroll-view ref="myScrollView"></scroll-view>加ref,一键回到顶部要用this.$refs.myScrollView.scrollTo({ scrollTop: 0 })(uni-app 3.0+) - H5 端兼容写法:
this.$refs.myScrollView.$el.scrollTop = 0 - 多个
<scroll-view></scroll-view>同时存在且都设scroll-y,容易互相劫持滚动事件,慎用
为什么 createSelectorQuery 拿不到页面滚动距离
有人想用 uni.createSelectorQuery().selectViewport() 查滚动位置,结果多数平台返回 null。这不是 API 写错了,而是设计如此:
-
uni.createSelectorQuery只查组件树内节点,页面滚动容器不属于任何组件树 - 小程序里根本没有
document,更没有scrollingElement - 强行在 mounted/onReady 里查
scrollTop,值恒为 0 —— 页面还没开始滚动 - 若真需要初始化滚动位置(比如恢复上次位置),应从
onLoad参数或本地缓存读,而非实时查询
最易被忽略的点:同一个页面里混用原生页面滚动和 <scroll-view></scroll-view> 时,onPageScroll 和 @scroll 的触发逻辑互斥,且恢复滚动位置时若没记录路径来源(是走页面还是 scroll-view),uni.pageScrollTo 或 scrollTo 很可能调错目标。











