在onReady中用uni.createSelectorQuery查询#searchInput节点并调用focus()实现自动聚焦;搜索历史用debounce节流+uni.setStorage异步保存,去重前trim字符串;点击历史项时更新输入值、触发搜索并uni.hideKeyboard收起键盘。

uni-app里怎么用uni.createSelectorQuery做搜索框聚焦?
搜索框要一进页面就自动聚焦,不能靠focus属性硬写——iOS下无效,Android部分机型也不响应。得用uni.createSelectorQuery手动查DOM再调focus()。
关键点是:必须等onReady之后执行,且要加exec回调确保节点已挂载:
onReady() {
setTimeout(() => {
uni.createSelectorQuery()
.select('#searchInput')
.fields({ node: true, size: true })
.exec(res => {
const input = res[0]?.node;
if (input) input.focus();
});
}, 100);
}
- 不用
mounted,因为uni-app的mounted不保证视图已渲染完成 - 加
setTimeout是防极快机型下节点还没生成;100ms足够,再短可能失败 -
#searchInput必须是<input>或<uni-input></uni-input>上写的id,class选择器无效
搜索历史怎么存进uni.setStorageSync又不卡UI?
每次用户搜完,把关键词push进数组再存本地,但直接uni.setStorageSync在主线程跑,输入频繁时会明显卡顿——尤其低端安卓机。
正确做法是节流 + 异步写入:
const saveHistory = debounce((keyword) => {
const history = uni.getStorageSync('searchHistory') || [];
const newHistory = [keyword, ...history.filter(k => k !== keyword)].slice(0, 10);
uni.setStorage({ key: 'searchHistory', data: newHistory }); // 用异步版
}, 300);
- 必须用
uni.setStorage(异步)而非uni.setStorageSync(同步),后者会阻塞渲染线程 - 去重逻辑放在存之前,避免每次读全量再filter,减少IO压力
- 限制10条是经验值:再多列表渲染变慢,且用户极少翻到第10条以后
点击历史记录后怎么清空输入并触发搜索?
用户点历史项,要立刻填入输入框、触发搜索、同时隐藏键盘——但input组件的confirm-type="search"只对软键盘回车有效,点列表项得手动模拟。
核心是三件事串行执行:
handleHistoryTap(keyword) {
this.searchValue = keyword;
this.doSearch(); // 你的搜索逻辑
uni.hideKeyboard(); // 主动收起键盘,否则iOS常残留
}
- 不能只改
v-model绑定的值,必须显式调doSearch(),否则搜索逻辑不会触发 -
uni.hideKeyboard()在Android上有时失效,可加setTimeout(() => uni.hideKeyboard(), 50)兜底 - 如果用了
uni-input组件,需确认它没拦截blur事件,否则键盘不收
为什么uni.getStorageSync('searchHistory')有时返回null?
不是代码写错,而是uni.getStorageSync在App端首次冷启动时可能读不到值——尤其Android上,storage初始化有延迟。
安全写法永远带默认值:
const history = uni.getStorageSync('searchHistory') || [];
- 不要用
== null或typeof === 'undefined'判断,getStorageSync出错时直接抛异常,不是返回null - 真遇到读不到的情况,大概率是开发者工具缓存bug,真机调试时极少发生;若线上偶发,说明storage被主动清空过(如用户清理应用数据)
- 敏感场景(比如历史记录影响功能入口)建议加一层try-catch,但日常搜索不需要
trim()再比较。这个细节不在API里,但直接影响体验。


















