iOS下Input聚焦延迟或失效是因系统300ms防误触机制及WKWebView对非用户直接触摸事件中focus()的静默忽略,需用@touchend替代@click并校验DOM挂载、移除干扰CSS、加用户交互兜底。
ios下input聚焦延迟不是代码写慢了,是系统强制加了300ms防误触窗口,且uni-app的focus()调用时机常卡在dom未就绪或wkwebview坐标计算错乱的节点上。
为什么@click触发focus会延迟甚至失效
iOS Safari(含微信、App内WKWebView)对自动focus有严格限制:非用户直接触摸事件上下文里调用focus()会被静默忽略。uni-app里用@click绑定this.$refs.input.focus(),本质是监听合成后的click事件,已错过系统允许的“主动交互”时间窗。
- 真机调试时
document.activeElement仍为body,说明焦点根本没切过去 - 哪怕加了
setTimeout(() => el.focus(), 0),在WKWebView中也可能因$nextTick延迟超120ms而失效 - H5端复现率高于App端,因为Safari对非用户手势的干预更激进
用@touchend替代@click并手动控制焦点
最轻量解法:不引入fastclick,改用@touchend并配合防误触和ref校验。
- 模板中绑定
@touchend.stop.prevent="focusInput",.stop阻断冒泡,.prevent禁用默认滚动行为 - 方法内先判断
document.contains(this.$refs.input),确保DOM已挂载 - 再执行
this.$refs.input.focus(),iOS会认可这是“用户触摸后立即响应” - 避免在
@touchend里调this.$nextTick或复杂计算,否则视图更新滞后会让光标位置错乱
动态创建input后focus失败的修复时机
v-if切换、弹窗内表单等场景,focus()常因ref未绑定或父容器transform干扰而静默失败。
- 不要在
onReady或mounted里直接调focus(),改用this.$nextTick(() => setTimeout(() => this.$refs.input?.focus(), 100)) - 若父容器用了
transform: translateZ(0)或will-change: transform,iOS会把input提升到独立合成层,坐标系错乱——必须移除这些CSS - 对
textarea,聚焦前先设style.height = 'auto'再读scrollHeight,否则高度坍缩会导致光标跳首行
自动聚焦场景必须加用户交互兜底
iOS不允许页面加载完自动弹键盘,但可以“用户点一下→立刻聚焦”。很多团队卡在“页面一开就focus”,其实该改成“用户首次点击任意空白区→聚焦input+弹键盘”。
- 监听
@touchstart在根容器上,记录this.hasUserInteraction = true - 在
onReady里检查if (this.hasUserInteraction) this.$refs.input.focus() - 若用户始终没点,不强求自动聚焦,避免白屏卡顿或键盘闪退
最麻烦的不是写几行代码,而是iOS不同版本对position: fixed + input的处理逻辑不一致:iOS 15.4修了光标偏移,却让键盘收起后页面不回落;iOS 16又改了scrollIntoView的block参数解析方式。所有表单页建议统一加page-meta监听setScrollTop,并在blur后主动scrollTo({scrollTop: 0})保底。











