搜索框focusout()事件异常:点击搜索结果时结果框意外关闭
问题根源
- 事件触发顺序冲突:点击搜索结果项时,输入框的
focusout事件会先于结果项的click事件执行——结果列表被隐藏后,click事件根本没机会触发,自然无法完成跳转。 - 重复绑定事件:你把
focusout/focusin放在了AJAX的done回调里,每次输入字符都会重新绑定一次事件,导致后续触发时多次执行隐藏/显示逻辑,进一步加重问题。
解决方法
方法1:延迟执行隐藏操作,给click事件留触发时间
通过setTimeout延迟隐藏结果列表,让click事件先执行完毕:
// jquery.js $(document).ready(function() { const $searchInput = $('.search-box input[type="text"]'); const $searchBox = $('#searchboxy'); let hideTimeout; // 只绑定一次focusout/focusin事件,不要放在AJAX回调里 $searchBox.on('focusout', function() { // 延迟100ms执行隐藏,给click事件留执行时间 hideTimeout = setTimeout(() => { $('.result').hide(); }, 100); }); $searchBox.on('focusin', function() { // 清除延迟定时器,避免输入框重新聚焦时结果被误隐藏 clearTimeout(hideTimeout); if ($searchInput.val().length) { $('.result').show(); } }); $searchInput.on("keyup input", function() { const inputVal = $(this).val(); const resultDropdown = $(this).siblings(".result"); if (inputVal.length) { $.get("includes/searchbar.inc.php", { term: inputVal }).done(function(data) { resultDropdown.html(data).show(); }); } else { resultDropdown.empty().hide(); } }); // 点击结果项的逻辑 $(document).on("click", ".result", function() { const $this = $(this); $searchInput.val($this.text()); $this.empty().hide(); // 清除延迟定时器,避免隐藏操作执行 clearTimeout(hideTimeout); }); });
方法2:判断失焦目标是否在搜索容器内
在focusout事件里,检查失去焦点后获得焦点的元素是否属于搜索框容器,如果是就不隐藏结果:
// jquery.js $(document).ready(function() { const $searchInput = $('.search-box input[type="text"]'); const $searchBox = $('#searchboxy'); $searchBox.on('focusout', function(e) { // 检查新焦点元素是否在搜索框容器内,不在才隐藏结果 if (!$searchBox.has(e.relatedTarget).length) { $('.result').hide(); } }); $searchBox.on('focusin', function() { if ($searchInput.val().length) { $('.result').show(); } }); $searchInput.on("keyup input", function() { const inputVal = $(this).val(); const resultDropdown = $(this).siblings(".result"); if (inputVal.length) { $.get("includes/searchbar.inc.php", { term: inputVal }).done(function(data) { resultDropdown.html(data).show(); }); } else { resultDropdown.empty().hide(); } }); $(document).on("click", ".result", function() { const $this = $(this); $searchInput.val($this.text()); $this.empty().hide(); }); });
额外优化点
- 用jQuery的
hide()/show()替代直接操作css('display'),写法更简洁且兼容性更好。 - 提前缓存DOM元素(比如
$searchInput、$searchBox),避免重复查询DOM,提升页面性能。 - 移除AJAX回调里的事件绑定逻辑,改为在
document.ready中只绑定一次,避免重复绑定导致的多次触发问题。
内容的提问来源于stack exchange,提问作者Votum
相关产品推荐
相关产品推荐

