最稳妥的跨平台自动聚焦方案是onReady中用uni.createSelectorQuery()查询真实DOM节点后在exec回调中调用focus(),因onReady确保视图初始化完成,而onLoad太早、onShow可能重复,且H5中focus属性无效、iOS微信需用户手势触发但首次进入合法。
不能靠 focus 属性硬写,h5 无效、ios 微信不响应、android 部分机型失焦——必须用 uni.createselectorquery() 或 $nexttick + ref.focus() 主动触发。
onReady 中用 createSelectorQuery 确保节点已挂载
这是最稳妥的跨平台方案,尤其适用于 tab 页面、条件渲染块或弹窗内搜索框。微信小程序要求聚焦必须发生在真实 DOM 节点就绪后,onLoad 太早,onShow 可能重复执行,onReady 是唯一能保证视图初始化完成的时机。
- 模板中给
<input>或<uni-search-bar></uni-search-bar>加id="searchInput"(注意不是ref) -
onReady里调用uni.createSelectorQuery().select('#searchInput').fields({ node: true }).exec() - 必须在
exec的回调里调node?.focus(),否则查不到节点 - 安卓微信偶尔需补
uni.showSoftInput({ onlyGetInput: true })唤键盘;iOS 通常不需要
用 ref + $nextTick 替代 focus 属性
focus="true" 在 H5 完全无效,在小程序也受限于渲染时机和 v-if 移除逻辑。统一走 ref + 方法调用才是可控路径。
- 模板中写
<input ref="searchInput" v-model="kw"> -
onReady或mounted(Vue3 setup 中可用onMounted)里加this.$nextTick(() => { this.$refs.searchInput?.focus() }) - 务必加
typeof this.$refs.searchInput?.focus === 'function'判断,避免 H5 下 ref 返回组件实例而非原生节点 - 如果用
v-if="showSearch"控制显示,每次切换都会销毁重建,focus属性只在首次生效;应改用v-show配合:focus="showSearch"
uni-search-bar 组件怎么自动聚焦
官方 uni-search-bar 默认不聚焦,改源码风险高且升级会覆盖。推荐封装一层,或直接用原生 <input> 更可控。
- 不要修改
components/uni-search-bar/uni-search-bar.vue里的show或showSync数据——那是内部状态,非聚焦开关 - 若坚持用该组件,可在其外层包一层
view,用id查询其内部input节点:.select('.uni-search-bar__input') - 更简单做法:弃用
uni-search-bar,自己写带 icon 和圆角的<input>,样式完全自由,聚焦逻辑也干净 - 吸顶需求用
position: sticky; top: 0即可,无需 JS 干预
为什么 iOS 微信里点一次才聚焦
本质是平台限制:微信小程序要求聚焦动作必须由用户手势(tap/click)触发,任何异步延时(setTimeout、Promise.then)都无法绕过。但页面首次进入属于“合法上下文”,只要 DOM 就绪就能聚焦——所以失败往往是因为查节点太早,或节点被 v-if 拦截未渲染。
- 用
uni.createSelectorQuery()时漏掉exec()回调,查到的是null - 在
onLoad里直接this.$refs.xxx.focus(),此时 DOM 还没生成 - 父容器用了
transform或fixed定位,导致焦点区域计算异常(iOS 尤其敏感) - 真机调试时关掉“调试器”再试——部分机型开启调试器会影响软键盘唤起逻辑
真正难的不是写几行代码,而是确认那个 input 节点此刻是否真实存在于当前页面的渲染树里。每次聚焦失败,先跑一遍 uni.createSelectorQuery().select('#xxx').boundingClientRect().exec(console.log),看到空对象就别往下试了。


















