jQuery Mobile enhanceWithin后输入框focus失效,求替代setTimeout的更佳方案
你遇到的这个问题本质是jQuery Mobile的DOM增强操作是异步队列化的——哪怕你同步调用了enhanceWithin(),它内部的DOM改造、组件初始化(比如给输入框套上自定义样式容器、绑定交互事件)并不会立刻完成。
当你紧接着调用focus()时,目标输入框可能还处于“未完全就绪”的状态:要么它的DOM结构还没被改造完成(比如实际可聚焦的是生成的子元素而非原input),要么浏览器的重排/重绘队列还没处理完增强后的DOM变更,导致focus()调用没有作用到正确的元素上。
而setTimeout(fn, 50)之所以能生效,是因为它把focus()的调用推迟到了下一个事件循环周期,这时候浏览器已经处理完了enhanceWithin触发的所有DOM操作和组件初始化,元素自然可以正常接收焦点。
与其依赖不确定的延迟时间,不如利用jQuery Mobile提供的异步完成通知机制来确保在增强完全结束后再执行focus操作,这里有两种推荐方案:
方案1:使用jQuery Promise监听增强完成
enhanceWithin()返回的jQuery对象可以结合.promise()来监听所有增强操作的完成,它会在队列中所有DOM增强任务结束后触发回调:
$selectedActionsContainer.enhanceWithin() .promise() .done(function() { $userInputNewBoxes.focus(); });
这个方法的优势是不需要关心具体是哪个组件被增强,只要容器内的所有增强操作完成就会执行focus,通用性很强。
方案2:监听特定组件的创建完成事件
如果你知道目标输入框会被jQuery Mobile初始化为某个特定组件(比如textinput),可以直接监听该组件的create事件,当组件初始化完成后立刻聚焦:
// 先绑定事件,再触发增强 $userInputNewBoxes.on("textinputcreate", function() { $(this).focus(); }); $selectedActionsContainer.enhanceWithin();
这种方式更精准,适合你明确知道目标元素类型的场景,避免等待容器内其他无关元素的增强完成。
如果以上方案都不生效,还可以检查一下$userInputNewBoxes是否指向了正确的元素:jQuery Mobile在增强输入框时,可能会把原input元素包裹在一个div容器里,这时候你可能需要通过$userInputNewBoxes.find("input")来获取实际可聚焦的原生input元素。
内容的提问来源于stack exchange,提问作者Vurbetan

