基于ShuffleJS自定义下拉选择组件的三类问题求助
自定义ShuffleJS搜索选择组件问题修复
背景
原本尝试用ShuffleJS实现<select>下拉框的实时搜索过滤未果,于是基于Stack Overflow方案自定义了组件:用<textarea>作为搜索输入框,选项存储在<ul>的<li>元素中,借助ShuffleJS处理过滤逻辑。表单内存在多个结构一致的该组件(如出发地/到达地选择器),采用了共享选项列表的设计,整体功能可用,但存在三类问题:
1. 下拉框关闭逻辑冲突:点击选项时<textarea>的onblur先触发导致选项点击失效
问题原因:点击选项时,<textarea>先失去焦点触发onblur,下拉框被隐藏,后续的选项点击事件无法执行。之前用延时处理存在竞态风险。
修复方案:
通过判断blur事件的relatedTarget(焦点转移的目标元素)是否属于当前组件内部元素,决定是否关闭下拉框;同时给选项点击事件添加标记,避免误判。
示例代码(jQuery):
$('.search-textarea').on('blur', function(e) { const $target = $(e.relatedTarget); // 若焦点未转移到组件内部元素,才关闭下拉框 if (!$target.closest('.search-select-component').length) { $(this).siblings('.options-list').hide(); } }); $('.options-list li').on('mousedown', function() { // 标记正在点击选项,避免blur时误关 $(this).closest('.search-select-component').data('is-clicking', true); }).on('mouseup', function() { const $component = $(this).closest('.search-select-component'); const $textarea = $component.find('.search-textarea'); // 复制选项内容到输入框 $textarea.val($(this).text()); // 隐藏下拉框并清除标记 $component.find('.options-list').hide(); $component.data('is-clicking', false); });
2. 键盘导航无响应:TAB键聚焦<textarea>时下拉框无法弹出
问题原因:仅监听了输入事件,未处理focus事件,导致通过TAB键聚焦时不会触发下拉框显示。
修复方案:
给<textarea>添加focus事件监听,只要聚焦就显示下拉框,同时触发一次空过滤让ShuffleJS显示所有选项。
示例代码:
$('.search-textarea').on('focus', function() { const $optionsList = $(this).siblings('.options-list'); $optionsList.show(); // 触发空过滤,确保所有选项显示 const shuffleInstance = $(this).closest('.search-select-component').data('shuffle'); shuffleInstance.filter(); });
3. 未搜索时无法选中选项:直接点击下拉选项无响应
问题原因:未搜索时ShuffleJS的初始过滤状态可能未正确加载,或者选项点击事件未绑定到所有可见元素。
修复方案:
初始化Shuffle时默认显示所有选项,同时用事件委托给所有选项绑定点击事件,确保点击时同步内容到输入框并关闭下拉框。
示例代码:
// 初始化Shuffle,默认显示所有选项 const shuffle = new Shuffle(document.querySelector('.options-list'), { itemSelector: 'li', filterMode: 'any', initialFilter: null }); // 用事件委托绑定点击事件,覆盖所有动态过滤后的选项 $('.options-list').on('click', 'li', function() { const $component = $(this).closest('.search-select-component'); const $textarea = $component.find('.search-textarea'); $textarea.val($(this).text()); $component.find('.options-list').hide(); // 触发输入框change事件,方便表单取值 $textarea.trigger('change'); });
内容的提问来源于stack exchange,提问作者bliako
相关产品推荐
相关产品推荐

