uni-app中宫格横向滑动应使用scroll-view而非swiper,需设scroll-x="true"、固定父容器宽高、子项用inline-block或flex布局,配合rpx宽度、手动吸附对齐及scroll-to平滑滚动,并注意三端兼容性问题。

uni-app 里用 scroll-view 实现宫格横向滑动,别碰 swiper
美团那种分类导航本质是「可拖拽、带惯性、不自动轮播」的横向宫格,swiper 默认带自动切换和翻页逻辑,强行关掉会卡顿、手势冲突,还难对齐。真要用,得切到 scroll-view + 手动控制滚动位置。
关键点:必须设 scroll-x="true",禁用 scroll-y,且父容器要固定宽高(尤其高度),否则内容塌陷;子项用 display: inline-block 或 flex 横向排列,不能靠 float。
-
scroll-view的scroll-with-animation设为true,否则滑动生硬 - 每个分类项宽度建议用
rpx固定(比如160rpx),避免不同屏幕下错行 - 如果分类项数量多,别一次性全渲染,用
v-for+:key,但注意scroll-view内部 DOM 更新可能触发重绘抖动
怎么让滑动后自动吸附到最近的宫格边界
原生 scroll-view 不支持 snap 对齐,得自己算。监听 scroll-left 变化,在 @scroll 回调里判断当前滚动位置离哪个宫格左边界最近,然后用 this.$nextTick(() => { this.scrollLeft = targetPos }) 强制跳转过去。
注意:直接在 @scroll 里调 scroll-to 会触发新一轮 scroll,造成循环。必须加节流或只在 scrollend 事件(H5 支持,App 和小程序需兼容)里执行。
- 每个宫格宽度假设是
160rpx,那吸附位置就是Math.round(scrollLeft / 160) * 160 - 小程序平台要小心
scroll-left单位是 px,不是 rpx,得用uni.upx2px(160)转换 - H5 端可直接用 CSS
scroll-snap-align: start,但 uni-app 编译后不一定透出,不推荐依赖
点击分类项时平滑滚动到对应位置,而不是突兀跳转
用户点某个分类,需要把整个宫格区域滚动过去,让该项居中或靠左显示。不能直接改 scroll-left 值,得用 scroll-view 的 scroll-to 方法,并传 duration。
问题常出在:没等 DOM 渲染完就去算位置,offsetLeft 拿到的是 0;或者滚动目标是相对 scroll-view 内容区的偏移,不是整个页面。
- 用
this.$nextTick包住获取元素位置的逻辑 - 用
uni.createSelectorQuery()查.category-item:nth-child(3)的boundingClientRect,比直接ref更可靠 -
duration设成300左右,太短像跳,太长像卡 - App 端
scroll-to有 bug,偶尔失效,建议 fallback 到直接赋值scroll-left+scroll-with-animation="true"
真机上滑不动、卡顿、回弹异常的几个硬坑
开发时在 H5 预览没问题,一上真机就各种诡异表现:iOS 微信里滑不动、Android App 滚动延迟半秒、小程序里松手后回弹过头。根本原因不是代码写错,而是平台限制和样式干扰。
- 父容器不能有
overflow: hidden,哪怕只是上级某个 div,都会截断 touch 事件 - 别给
scroll-view加transform(比如scale或translateZ),iOS 下会禁用原生滚动加速 - 分类图标用
image标签时,记得加mode="aspectFill",否则图片拉伸会撑高容器,导致滚动区域计算错乱 - 微信小程序基础库低于 2.10.3 时,
scroll-view的scroll-end事件不触发,得用setTimeout模拟“静止”状态
宫格滑动看着简单,实际每一步都在跟平台底层滚动机制掰手腕。最麻烦的不是怎么写,而是怎么让三端表现一致——H5 用 CSS 滚动,小程序靠 scroll-view,App 端还得单独 patch 原生层。留个心眼:上线前务必在 iOS 微信、安卓微信、iOS App、安卓 App 四个环境各测三遍滑动和点击响应。


















