移动端Safari下拉选框选择后聚焦输入框触发Blur问题解决
解决移动端Safari下拉选框选择后聚焦输入框仍触发blur的问题
问题根源是移动端Safari的事件处理时序差异:在select的onchange中调用input.focus()时,Safari会先执行聚焦操作,但随后仍会触发select的blur事件,这是浏览器原生行为导致的。且直接用setTimeout会因延迟无法唤起键盘,以下是可行解决方案:
方案1:利用微任务延迟执行focus(可唤起键盘)
将focus操作放入微任务队列(比如Promise.resolve()),保证在当前事件循环结束后执行,既不会有setTimeout的明显延迟,又能正常唤起键盘:
<select id="demo_1"> <option value="">Select an option</option> <option value="Firefox">Firefox</option> <option value="Chrome">Chrome</option> <option value="Edge">Edge</option> </select> <div>i don't like saFari</div> <input type="text" id="demo_2" /> <script> document.getElementById('demo_1').addEventListener('change', function() { if (this.value !== '') { Promise.resolve().then(() => { document.getElementById('demo_2').focus(); }); } }); // 按需阻止select的blur事件逻辑 document.getElementById('demo_1').addEventListener('blur', function(e) { const activeEl = document.activeElement; // 判断是否是聚焦到目标输入框导致的blur if (activeEl && activeEl.id === 'demo_2') { e.preventDefault(); // 若有自定义blur处理逻辑,可在此跳过执行 } }); </script>
方案2:用pointerdown标记切换状态(应对极端场景)
如果微任务方案仍有问题,可在select的pointerdown事件中标记焦点切换状态,再在blur事件中判断是否阻止:
<select id="demo_1"> <option value="">Select an option</option> <option value="Firefox">Firefox</option> <option value="Chrome">Chrome</option> <option value="Edge">Edge</option> </select> <div>i don't like saFari</div> <input type="text" id="demo_2" /> <script> let isSwitchingFocus = false; document.getElementById('demo_1').addEventListener('pointerdown', function() { isSwitchingFocus = true; }); document.getElementById('demo_1').addEventListener('change', function() { if (this.value !== '') { document.getElementById('demo_2').focus(); isSwitchingFocus = false; } }); document.getElementById('demo_1').addEventListener('blur', function(e) { if (isSwitchingFocus) { e.preventDefault(); isSwitchingFocus = false; } }); </script>
核心提示
- 微任务方案更推荐,无需额外状态变量,且能保证聚焦操作在正确时机执行,同时唤起键盘。
- 阻止
blur事件的关键是:触发blur时判断是否为主动切换到目标输入框的操作,再决定是否阻止默认行为或后续逻辑。
内容的提问来源于stack exchange,提问作者Kia Faraji
相关产品推荐
相关产品推荐

