scroll-view滚动失效或卡顿的根本原因是高度未显式设置,必须用100vh等确定值而非100%或flex:1;ios需配disablescroll:true、bounces="false"并真机验证enhanced效果。

scroll-view高度没设死,滚动直接失效或卡顿
很多开发者以为只要写了 scroll-y 就能滑,结果在H5端一动不动,或者滑两下就卡住——根本原因是 scroll-view 没有确定高度。它不像普通 view 那样靠内容撑开,必须显式定义高度,否则浏览器无法计算滚动上下文。
- 父容器必须有明确高度(比如
height: 100vh),不能依赖min-height或flex: 1模糊计算 - 推荐写法:
.scroll-container { height: 100vh; display: flex; flex-direction: column; }+.my-scroll-view { flex: 1; } - H5端慎用
height: 100%,它依赖所有祖先元素都有确定高度,链路一断就退化成height: auto - nvue 页面中可用
flex: 1更稳妥,但H5端必须走vh或固定像素值
iOS上要滑两次才动,其实是事件抢夺和回弹干扰
这不是bug,是iOS WKWebView对嵌套滚动的保守策略:第一次滑动被页面级回弹吃掉了,第二次才落到 scroll-view 上。关键不是“怎么让它动”,而是“怎么让系统别犹豫”。
- 必须在
pages.json对应页面的style里加"disableScroll": true,否则页面自带滚动会劫持 touch 事件 -
scroll-view标签上必须显式写bounces="false",CSS 的-webkit-overflow-scrolling: touch不足以禁用回弹 - 绝对不要在
scroll-view外层或body上写@touchmove.prevent,哪怕只有一处,整个手势链就断了 - 真机调试前关掉 HBuilderX 的「启用调试基础库」选项,它会在iOS上注入额外监听,放大卡顿
enhanced=true 不生效?大概率是高度没锁死或没真机验证
enhanced 是iOS滚动性能的关键开关,但它不是“开了就变快”,而是一个有硬前提的增强模式:只有当 scroll-view 高度完全确定时,它才会启用原生滚动代理;否则自动降级为普通 div 滚动,性能毫无提升。
- 高度必须是静态可计算的(
vh、固定像素),不能依赖this.$nextTick动态赋值后再开enhanced - 开启后必须真机测试,模拟器和H5预览几乎不复现iOS问题,因为内核不同
- 搭配
bounces="false"和图片懒加载(lazy-load)效果更明显,在iPhone SE二代上帧率提升3倍以上 - 如果用了
v-for列表,每个 item 的:key必须是稳定唯一值,禁止用:key="index"
滑动到底部卡3秒?多半是 onReachBottom 被高频触发阻塞主线程
用户快速上拉触底时,onReachBottom 可能在1秒内触发十几次,每次调用 this.setData 合并新数据,JS堆栈积压,主线程直接90%占用率冻结——这不是“慢”,是“被堵死”。
- 必须对
onReachBottom做节流,建议用throttle控制为至少500ms间隔触发一次 - 分页请求返回后,避免直接
this.list = [...this.list, ...newData],改用this.$set(this, 'list', [...this.list, ...newData])减少响应式开销 - 长列表优先换用
uv-list或 nvue 的list,H5端虚拟滚动比手写scroll-view+ offset 计算更可靠 - 检查是否在滚动监听里做了同步DOM操作或复杂校验,这类逻辑一律移到
scrollend后执行
vh 没写对、disableScroll 漏配、或者 enhanced 在降级状态下空转。性能优化不是堆参数,而是让每一层约束都严丝合缝。











