iOS 13/14调用input.focus()无法唤起键盘,求替代方案
我之前也踩过这个一模一样的坑!iOS 13 之后苹果对自动唤起键盘做了非常严格的限制——核心原因是为了防止页面滥用自动弹窗打扰用户:只有在用户主动发起的交互(比如点击、触摸操作)的同步回调里调用 focus(),才能成功唤起键盘;非用户触发的场景(比如自定义事件、定时器、异步回调)里的 focus() 都会被系统直接拦截,这就是你在 iOS 12 正常、13+ 失效的根本原因。
结合你的代码场景,给你几个可行的解决思路:
1. 确保 focus() 调用处于用户交互上下文
你的代码监听了自定义的 changeFocus 事件,如果这个事件不是直接由用户的点击/触摸操作触发的(比如是自动触发、定时器触发),那 focus() 必然失效。你需要调整逻辑,把焦点切换的逻辑绑定到用户真实的交互动作上:
比如如果是用户点击按钮触发焦点切换,直接在 click 事件回调里执行跳转,而不是通过自定义事件中转。
2. 利用 readonly 属性的小技巧
针对 iOS 的限制,可以通过临时移除 readonly 属性的方式辅助唤起键盘,适配你的代码的示例如下:
jQuery(document).on("changeFocus", function(event, element) { if (_wlContainerElemRef.nativeElement.contains(element)) { var elementPosition = focusableElements.indexOf(element); if (elementPosition < focusableElements.length - 1) { var nextElemment = focusableElements[elementPosition + 1]; // 临时移除readonly(如果你的输入框设置了该属性) nextElemment.removeAttribute('readonly'); nextElemment.focus(); // 可选:若需要保持readonly状态,focus后再恢复 // setTimeout(() => nextElemment.setAttribute('readonly', true), 100); } else if (elementPosition == focusableElements.length - 1) { focusableElements[elementPosition].blur(); } } });
原理是 iOS 对设置了 readonly 的输入框,不会拦截用户交互触发的焦点唤起,临时移除后调用 focus() 就能绕过系统限制。
3. 调整自定义事件的触发时机
如果必须保留 changeFocus 自定义事件,要确保这个事件是在用户交互的同步流程中触发的。比如在用户的 keydown(比如Tab键切换焦点)或 click 事件里触发:
// 示例:在用户按Tab键时触发changeFocus jQuery(document).on('keydown', function(e) { if (e.key === 'Tab') { e.preventDefault(); jQuery(document).trigger('changeFocus', [当前焦点元素]); } });
这样 changeFocus 的回调就处于用户交互的上下文里,调用 focus() 就能正常唤起键盘。
补充说明
iOS 12 及之前没有这么严格的限制,苹果在 iOS 13 中收紧这一规则属于系统层面的行为变更,不是你的代码有问题,只需要适配新的系统交互规范即可。
内容的提问来源于stack exchange,提问作者Amr Maghraby

