应分层加载+懒解析:按省拆分json、缓存后按需读取,城市数据带拼音索引;u-index-list需动态生成filteredindexlist并用:key强制重渲染;搜索用防抖+空值短路;匹配须标准化拼音后startswith。

城市数据怎么加载才不卡顿
本地城市 JSON 文件动辄几 MB,直接 import 进页面会导致首屏白屏、打包体积暴涨。真机上尤其明显——iOS 小程序常因内存超限直接崩溃。
正确做法是分层加载 + 懒解析:
- 把全国城市按省级拆成多个小文件(如
province/shandong.json),用uni.getStorage缓存一次后按需读取 - 首次只加载省级列表;用户点开某省再动态
import('./cities/shandong.js')(注意:小程序里不能用动态import(),得改用require或提前预载) - 城市名字段必须带拼音索引(如
{name: "杭州", pinyin: "hangzhou"}),否则中文模糊匹配只能靠indexOf,搜“杭”能命中,“杭”字在中间就漏掉
u-index-list 怎么配合搜索联动
原生 u-index-list 不响应外部搜索状态,强行用 v-if 切换整个组件会闪屏,且索引字母条错位。
关键要绕过渲染层,直接操作数据流:
- 搜索时不要清空
indexList和itemArr,而是生成新数组:this.filteredIndexList = [...new Set(filteredCities.map(c => c.pinyin.charAt(0).toUpperCase()))] - 用
computed重算itemArr:对每个首字母,过滤出匹配的城市子集,保持原有分组结构 - 给
u-index-list加:key="searchKeyword || 'default'"强制重渲染,避免缓存旧 DOM
输入框 @input 还是 @confirm 触发搜索
移动端键盘回车键不可靠(iOS 微信里经常不触发 @confirm),纯 @input 又容易高频请求拖垮 UI。
折中方案是加防抖 + 空值短路:
- 用
setTimeout做 300ms 防抖,但必须在data里声明searchTimer: null,否则多次触发会覆盖 timer ID 导致漏执行 - 输入为空字符串时,立刻恢复原始城市列表,不走防抖逻辑(否则用户删光文字还要等 300ms)
- 如果后端支持,把搜索接口改成 GET + query 参数,方便 CDN 缓存重复关键词,比如搜“北”和“北京”共用一个缓存 key
为什么搜“shang”匹配不到“上海”
常见错误是直接对中文做 includes 或正则 /shang/i,但拼音转换没做标准化处理。
真正可用的匹配逻辑必须包含三步:
- 输入文本统一转小写 + 去空格:
keyword = keyword.trim().toLowerCase() - 城市拼音字段提前转为小写并去音调(用
pinyin-pro库或简单映射表) - 匹配用
city.pinyin.startsWith(keyword)而不是includes,否则搜“hai”会命中“上海”“海口”“海宁”,但用户本意大概率是“上海”
拼音库选型很关键:pinyin 包体积大、chinese-to-pinyin 不支持多音字,生产环境建议用 pinyin-pro 的轻量版,或自己维护一份常用城市拼音映射表。











