scroll-view垂直滚动需显式设置height或max-height,禁用enable-back-to-top,内容用view包裹text并加缓冲空text,避免input等聚焦元素;swiper垂直公告不可靠,应使用requestAnimationFrame精准控制scrollTop实现无缝循环。

scroll-view 垂直滚动必须设固定高度和 scroll-y
不设 height 或 max-height,scroll-view 就不会触发滚动逻辑,真机上直接“点不动”或“滑一下就停”。这不是 bug,是规范行为——scroll-view 依赖容器尺寸计算可滚动区域。
常见错误写法:.container { flex: 1; } 而没给父级设高度;或者用 vh 单位但没考虑状态栏/导航栏高度,导致 iOS 下实际可用高度不足。
- 必须显式设置
height(如height: 80rpx)或max-height - 禁用
enable-back-to-top,否则 iOS 真机会在滚动中意外跳回顶部 - 内容区用
view包裹所有text,每条公告后加一个空text(视觉缓冲用),避免滚到底部时“戛然而止” - 不要在内容里放
input、textarea或任何可聚焦元素,它们会劫持 touch 事件,导致滚动失灵
别用 swiper 做垂直公告,它在 iOS 上不可控
swiper 的垂直模式在 uni-app 中存在底层渲染缺陷:iOS 真机容易滚动中断、回弹异常、touchstart 后无法持续拖动。官方文档没明说,但大量线上项目验证过——只要公告需要自动+无缝+可暂停,swiper 就不该出现在选项里。
根本原因在于 swiper 依赖 transform + transition 模拟滚动,而 iOS webview 对这类动画的合成层调度不稳定;scroll-view 则走原生滚动通道,更可靠。
- 即使开启
vertical和circular,也无法精准控制单条停留时间 - 数据更新后调用
this.$nextTick(() => this.$refs.swiper?.change()) 容易失步 - 想监听滚动位置?
@change触发频率低且不准,@animationfinish在 iOS 上常不触发
scrollTop + requestAnimationFrame 是唯一稳解
用 setInterval 每 50ms 加 1px scrollTop 看似简单,但在低端安卓机上掉帧明显,iOS 上还可能因渲染延迟导致赋值被丢弃。真正可控的方式是绑定 requestAnimationFrame,结合时间戳算偏移量,强制对齐 60fps。
关键不是“动起来”,而是“动得准”:暂停时不能清状态,恢复时要从断点继续,否则会跳帧或错位。
- 用
let startTime = 0, elapsed = 0, baseTop = 0记录滚动上下文 - 每次 raf 回调里计算
delta = (now - startTime) * speed,再设this.scrollTop = baseTop + delta - 暂停时只停止 raf 循环,
elapsed和baseTop保持不变 - iOS 平台下设
scrollTop前必须加await this.$nextTick()(Vue 2 用new Promise(resolve => this.$nextTick(resolve)))
无缝循环不是靠复制数组,而是 scrollTop 归零+forceUpdate
很多人学“虚拟长列表”拼接数据,结果内存暴涨、v-for 渲染卡顿。其实垂直公告的无缝,只需要在滚到底部时把 scrollTop 瞬间归零,并触发一次强制重绘——用户看到的是“自然接上”,不是“闪一下再续”。
难点在于时机:归零太早会漏掉最后一条,太晚会看到空白帧;而且 iOS 下归零后若不等下一帧就继续滚动,新值会被忽略。
- 判断条件不是
scrollTop >= contentHeight - containerHeight,而是scrollTop + containerHeight >= contentHeight - 1(留 1px 容差) - 归零后立即执行
this.$nextTick(() => { this.scrollTop = 0; }),确保 DOM 更新完成 - 不要在
@scroll里做重置逻辑——该事件在滚动中高频触发,会拖慢主线程 - 数据更新时(比如 push 新公告),必须手动重置
startTime和baseTop,否则滚动节奏错乱
滚动逻辑本身不复杂,难的是跨平台一致性。iOS 的渲染延迟、安卓的帧率抖动、H5 的事件冒泡干扰——这些细节不处理,模拟器跑得再顺,真机一上就露馅。











