WordPress中点击外部区域时Autofill下拉框无法隐藏问题
WordPress自动补全下拉框点击外部不隐藏修复
问题说明
站点基于WordPress搭建,通过给输入框绑定keyup事件实现自动补全:输入时向后端发起AJAX请求拉取匹配数据,渲染到下拉候选列表。当前异常为点击自动补全下拉框外部区域时,下拉框无法自动关闭隐藏。
原有实现代码:
jQuery("#edit-full-name").keyup(function(e) { jQuery("#fullnamelist").empty(); if (e.which == 8 || e.which == 46) return false; jQuery.ajax({ type: "POST", url: my_ajax_object.ajax_url, dataType: "json", data: { action: 'autocomplete_name', text: jQuery(this).val(), }, beforeSend: function() { jQuery("#edit-full-name").css("background", '#FFF url(' + my_ajax_object.theme_path + '/LoaderIcon.gif) no-repeat 165px'); }, complete: function() { jQuery("#edit-full-name").css("visibility", "hidden"); }, cache: false, success: function(data) { jQuery("#fullnamelist").empty(); jQuery.each(data, function(i, obj) { jQuery("#fullnamelist").append('<li>' + obj + '</li>'); }) jQuery("#fullnamelist li").bind("click", function() { setText(this); }); }, complete: function() { jQuery("#edit-full-name").removeAttr("style"); } }) })
问题原因
- 原有代码没有全局监听点击事件,未做点击目标区域判断,不会触发外部点击隐藏下拉的逻辑
- 原AJAX配置中存在两个同名
complete回调,JS对象同名属性会被后者覆盖,第一个设置输入框visibility的逻辑完全不会执行 - 每次AJAX请求成功后都给li元素重复绑定click事件,存在内存浪费
- 选中下拉选项后没有主动隐藏下拉框,会出现选值后列表残留的问题
修复后代码
// 监听全局点击,处理点击外部隐藏下拉逻辑 jQuery(document).on('click', function(e) { const clickTarget = jQuery(e.target); // 点击区域既不是输入框,也不在下拉列表范围内时,清空并隐藏下拉 if (!clickTarget.is('#edit-full-name') && !clickTarget.closest('#fullnamelist').length) { jQuery('#fullnamelist').hide().empty(); } }) // 输入框keyup自动补全逻辑 jQuery('#edit-full-name').keyup(function(e) { const $input = jQuery(this); const $nameList = jQuery('#fullnamelist'); $nameList.empty().show(); // 按下退格/删除键时不发起请求,直接清空下拉 if (e.which === 8 || e.which === 46) { $nameList.empty(); return false; } jQuery.ajax({ type: 'POST', url: my_ajax_object.ajax_url, dataType: 'json', data: { action: 'autocomplete_name', text: $input.val() }, beforeSend: function() { $input.css('background', `#FFF url(${my_ajax_object.theme_path}/LoaderIcon.gif) no-repeat 165px`); }, cache: false, success: function(res) { $nameList.empty(); jQuery.each(res, function(index, item) { $nameList.append(`<li>${item}</li>`); }) }, complete: function() { $input.removeAttr('style'); } }) }) // 下拉选项点击填充逻辑,用事件委托避免重复绑定 jQuery(document).on('click', '#fullnamelist li', function() { setText(this); // 选中值后主动隐藏下拉 jQuery('#fullnamelist').hide().empty(); })
关键逻辑说明
- 全局点击判断用
closest()方法匹配下拉列表祖先元素,兼容li标签内部嵌套子元素的场景,不会出现点击li内部元素被误判为外部点击的问题 - 下拉选项点击逻辑改用事件委托实现,无需每次渲染列表后重新绑定事件,性能更好
- 合并了原代码重复的complete回调,修复原有逻辑冲突
- 选中选项、点击外部两个场景都做了下拉隐藏/清空处理,避免列表残留
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

