You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 01:37:20