uni-indexed-list不能开箱即用,仅负责渲染和@click事件,滚动定位、拖拽、高亮、悬浮提示需用scroll-view手动实现;须设固定高度、规范id、启用scroll-with-animation;首字母提取推荐pinyin-pro;分组需先排序;touchmove需防抖并阻止默认行为;真机测试至关重要。
uni-indexed-list 组件不能直接拿来就用,它只管渲染和触发 @click,滚动定位、拖拽索引、首字母高亮、悬浮提示全得自己补。
scroll-view 必须设固定高度且启用动画
不设 height,scroll-into-view 会完全失效;H5 端不加 scroll-with-animation="true",跳转就是生硬闪动。
-
scroll-view的height必须是具体数值(如calc(100vh - 120px)),不能是100%或auto - H5 端务必显式写
scroll-with-animation="true";App 和小程序默认支持,但 iOS App 偶尔失灵,可加兜底:this.$refs.scrollView?.scrollTo({ scrollTop: targetTop }) - 每个分组容器的
id必须严格匹配索引点击传入的值,比如右侧点"Z",对应分组id就得是"id_Z"(大小写、下划线、空格都不能差)
首字母提取别手写正则,用 pinyin-pro
中文姓名“欧阳修”“阿Q”“360员工”靠 charAt(0) 或简单正则根本不可靠,多音字、符号、数字开头全崩。
- 安装:
npm install pinyin-pro - 取大写首字母:
pinyin('张三', { style: 'first-letter' }).toUpperCase()→"Z" - 必须做兜底:
const initial = pinyin(name || '', { style: 'first-letter' })?.toUpperCase() || '#' - 别用已停更的
pinyin或chinese-to-pinyin,它们在 H5 或小程序里常报global is not defined
分组前先排序,再按首字母聚类
微信通讯录不是先分组再排序,而是先按拼音全局排序,再切片归组——否则“A”组里名字乱序,用户一眼就能看出不对劲。
- 排序用
localeCompare最稳:list.sort((a, b) => a.name.localeCompare(b.name, 'zh-CN')) - 分组后过滤空项:
groups.filter(g => g.list.length > 0),避免索引栏出现无数据的孤立字母 - 索引数组(
indexList)必须动态生成,不能硬写['A','B',...,'Z']——真实数据可能只有 A、C、F、#
右侧索引栏的 @touchmove 必须节流+阻止默认行为
手指一滑,@touchmove 每秒触发几十次,不节流就疯狂调 scroll-into-view,结果是滚动卡顿、跳错位置、甚至页面整体被拖拽偏移。
- 监听
@touchstart记下初始pageY,@touchmove里用touches[0].pageY反推当前字母 - 必须加
e.preventDefault(),否则 iOS/Android 会触发页面全局拖拽 - 节流推荐用
setTimeout清除旧定时器,间隔设50ms足够响应又不爆炸 -
@touchend后记得清空高亮状态,不然松手后字母还亮着
真机测试比模拟器重要得多——H5 滚动惯性、小程序 touch 坐标偏移、iOS App 的 scrollTop 微小偏差,全得在真机上反复调。尤其是右侧索引栏的触控区域,手指宽度、屏幕密度、系统手势冲突,稍不注意就点不准。











