如何在JavaScript中判断焦点是否在文件选择器对话框上
解决方案
可以通过标记文件输入框的点击状态,结合文件选择的change事件和延迟判断,来区分是打开文件选择器导致的失焦,还是真正离开输入框的失焦。具体实现如下:
核心思路
- 给
input[type="file"]绑定click事件,设置临时标记,表示用户正在打开文件选择器。 - 在
focusout事件中,先检查这个标记:如果是刚点击过文件输入框,就跳过后续逻辑,并通过短暂延迟重置标记(处理用户取消选择文件的情况)。 - 绑定
change事件,在用户选择文件后立即重置标记。
修改后的代码实现
JavaScript 版本
// 作用域内的标记变量,记录是否刚点击了文件输入框 let isFilePickerOpening = false; function inputFocusOut(event, el) { let row = el.closest('tr'); let curFocus = event.relatedTarget; let moveOn = true; // 新增:判断是否是文件选择器打开导致的失焦 if (el.nodeName === 'INPUT' && el.type === 'file' && isFilePickerOpening) { moveOn = false; // 延迟重置标记,处理用户取消选择文件的情况 setTimeout(() => { isFilePickerOpening = false; }, 100); } else if(/* 原有动态添加行的判断逻辑 */) { // 原有逻辑:处理动态添加行的情况 moveOn = false; } else if(curFocus) { // 原有逻辑:检查是否在同一行 if(curFocus.closest('tr') === row) { moveOn = false; } } if(moveOn) { // 检查值变化并执行后续逻辑 // ... 你的原有代码 } } // 给所有文件输入框绑定事件 document.querySelectorAll('input[type="file"]').forEach(fileInput => { fileInput.addEventListener('click', () => { isFilePickerOpening = true; }); // 文件选择完成后重置标记 fileInput.addEventListener('change', () => { isFilePickerOpening = false; }); });
jQuery 版本
let isFilePickerOpening = false; function inputFocusOut(event, el) { let $row = $(el).closest('tr'); let curFocus = event.relatedTarget; let moveOn = true; if ($(el).is('input[type="file"]') && isFilePickerOpening) { moveOn = false; setTimeout(() => { isFilePickerOpening = false; }, 100); } else if(/* 原有动态添加行的判断逻辑 */) { moveOn = false; } else if(curFocus) { if($(curFocus).closest('tr').is($row)) { moveOn = false; } } if(moveOn) { // 检查值变化并执行后续逻辑 // ... 你的原有代码 } } // 绑定事件 $('input[type="file"]').on('click', function() { isFilePickerOpening = true; }).on('change', function() { isFilePickerOpening = false; });
说明
- 当用户点击文件输入框时,
isFilePickerOpening被设为true,此时触发的focusout会直接跳过后续逻辑,避免误判。 - 延迟100ms重置标记是为了覆盖用户打开文件选择器后取消选择的场景,确保标记能被正确重置,不影响后续的失焦判断。
- 文件选择完成后,
change事件会立即重置标记,保证后续操作的正常执行。
内容的提问来源于stack exchange,提问作者user3517375
相关产品推荐
相关产品推荐

