正确姿势是:scroll-view需设宽高、white-space: nowrap,子项用inline-block+固定宽;滚动用scrollIntoView或计算offsetLeft居中;点击驱动current,scroll-end校准;禁用scroll-with-animation和可聚焦组件。
uni-app里用
实现水平滚动导航的正确姿势
直接说结论:不能只靠
开个开关就完事,得配合
、
和精确的
控制,否则在iOS和部分安卓WebView里会卡顿、跳项、甚至不滚动。
常见错误是把
当
用,里面塞一堆
却不设父容器宽度或子项排列方式——结果就是“看着写了滚动,实际点不动、滑不走、回弹错位”。
必须显式设置
和
(哪怕只是
),不能依赖内容撑开
子元素要用
(不是
),并加
到父
上
每个分类项建议固定
(如
),避免不同文字长度导致布局抖动
触发滚动时别直接改
为像素值,要用
或计算
,否则H5端容易失准
点击分类自动居中滚动的实现逻辑(含兼容处理)
闲鱼那种“点哪个,哪个就滑到中间”,不是靠
,而是靠
+ 动态
,但uni-app的
在小程序和H5行为不一致:H5需要先
等DOM渲染完成,小程序则要确保
唯一且非动态生成。
典型翻车场景:用
循环生成
,但没加
,导致Vue复用节点后
找不到目标。
每个分类
必须带
,且
值静态可预测(如
、
)
H5端调用
比直接赋值更稳
想居中,不能只靠
,得手动算偏移:
安卓低端机上频繁滚动可能丢帧,建议加
节流,300ms内最多触发一次
tab高亮同步与
状态管理的坑
很多人把
绑定到
的
,然后监听
事件反推当前项——这在快速滑动时极易误判,尤其列表项宽度不均或有padding时。
真正靠谱的方式是:只响应点击,滑动仅作视觉反馈;高亮状态完全由
驱动,滑动结束再用
事件校准一次(仅兜底)。
不要在
中实时计算当前项,性能差还不准;
才是唯一可信时机
变量必须是
类型,别传字符串,否则
判断会失效
高亮样式别用
(安卓下常模糊),改用
更清晰
如果分类过多(>15个),建议做懒加载:只渲染可视区域前后各2个,其余用占位
真机调试时iOS滚动卡顿的三个硬解法
iOS微信/支付宝小程序里
水平滚动卡,90%是因为开启了
或者用了
动画干扰了原生滚动线程。
别信“加
就行”,uni-app里这个CSS根本不起作用;真正有效的只有三条:
关掉
,所有滚动用
赋值+
代替
整个
外层加
,防止父容器截断滚动事件
分类项内部禁用
、
、
等可聚焦组件,iOS会强制切输入法上下文导致卡顿
复杂点在于:滑动惯性、回弹、边界吸附这些体验细节,uni-app没暴露底层API,只能靠反复测
变化速率+手写缓动函数模拟,这部分没标准解法,得按机型微调。
scroll-viewscroll-xwhite-space: nowrapdisplay: inline-blockscroll-leftscroll-viewdivviewscroll-viewwidthheightheight: 80rpxdisplay: inline-blockflexwhite-space: nowrapscroll-viewwidth160rpxscroll-leftscrollIntoViewoffsetLeftscroll-toscroll-into-viewidscroll-into-viewsetTimeoutidv-forid="cate-{{index}}":keyscroll-into-viewviewididcate-0cate-1this.$nextTick(() => { this.scrollLeft = ... })scroll-into-viewscrollLeft = target.offsetLeft - (containerWidth - itemWidth) / 2throttlecurrentcurrentscroll-viewscroll-leftscrolldata.currentscroll-endscrollscroll-endcurrentNumberv-ifborder-bottombox-shadow: 0 -4rpx 0 #ff6700viewscroll-viewscroll-with-animationtransformwill-change: scroll-positionscroll-with-animationscroll-leftscrollIntoViewscroll-viewstyle="overflow: hidden;"inputtextareapickerscroll-left