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

Twitter Typeahead Bloodhound:在sorter中获取当前搜索框的搜索字符串

Hey Bernd,我完全懂你的烦恼——页面上有多个搜索框时,直接用类选择器$('.searchfield').val()拿值确实会混乱,根本没法确定用户正在操作哪一个。咱们可以从Bloodhound和Typeahead的绑定逻辑入手,用以下两种方法解决:

方法一:为每个搜索框创建独立的Bloodhound实例

这是最稳妥的方案,因为每个搜索框都拥有专属的Bloodhound实例,sorter里可以直接通过闭包捕获当前输入框的引用,精准拿到对应的值:

$('.searchfield').each(function() {
  // 捕获当前搜索框的DOM引用
  var $currentInput = $(this);
  
  // 为当前搜索框创建专属的Bloodhound实例
  var suggestions = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    source: /* 你的数据源 */,
    sorter: function(a, b) {
      // 直接用当前输入框的引用获取值,不会和其他搜索框混淆
      var input_string = $currentInput.val();
      input_string = input_string.split(/[ \-]+/);
      input_string = input_string[0].toLowerCase();
      
      var aArray = a.name.toLowerCase().split(/[ \-]+/);
      var bArray = b.name.toLowerCase().split(/[ \-]+/);
      var apos = 0, bpos = 0;
      
      for (var i = 0; i < aArray.length; i++) {
        if (aArray[i].indexOf(input_string) !== -1) {
          apos = i;
          break;
        }
      }
      for (i = 0; i < bArray.length; i++) {
        if (bArray[i].indexOf(input_string) !== -1) {
          bpos = i;
          break;
        }
      }
      
      return apos < bpos ? -1 : (apos > bpos ? 1 : 0);
    }
  });

  // 初始化当前搜索框的Typeahead
  $currentInput.typeahead({
    hint: true,
    highlight: true,
    minLength: 1
  }, {
    name: 'suggestions',
    source: suggestions,
    display: 'name'
  });
});

方法二:复用Bloodhound实例,通过事件传递当前输入值

如果不想创建多个Bloodhound实例,也可以借助Typeahead的typeahead:as-you-type事件,把当前活跃搜索框的输入值存到Bloodhound实例上,供sorter读取:

// 创建共享的Bloodhound实例
var suggestions = new Bloodhound({
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  source: /* 你的数据源 */,
  sorter: function(a, b) {
    // 读取之前存储的当前输入值,做个容错处理
    var input_string = this._currentInputValue;
    if (!input_string) return 0;
    
    input_string = input_string.split(/[ \-]+/);
    input_string = input_string[0].toLowerCase();
    
    var aArray = a.name.toLowerCase().split(/[ \-]+/);
    var bArray = b.name.toLowerCase().split(/[ \-]+/);
    var apos = 0, bpos = 0;
    
    for (var i = 0; i < aArray.length; i++) {
      if (aArray[i].indexOf(input_string) !== -1) {
        apos = i;
        break;
      }
    }
    for (i = 0; i < bArray.length; i++) {
      if (bArray[i].indexOf(input_string) !== -1) {
        bpos = i;
        break;
      }
    }
    
    return apos < bpos ? -1 : (apos > bpos ? 1 : 0);
  }
});

// 为每个搜索框绑定Typeahead并监听输入事件
$('.searchfield').each(function() {
  var $currentInput = $(this);
  $currentInput.typeahead({
    hint: true,
    highlight: true,
    minLength: 1
  }, {
    name: 'suggestions',
    source: suggestions,
    display: 'name'
  }).on('typeahead:as-you-type', function(e, query) {
    // 把当前输入的内容存到Bloodhound实例上
    suggestions._currentInputValue = query;
  });
});

两种方法里,我更推荐第一种,因为它完全避免了多个搜索框之间的状态冲突,逻辑更清晰,维护起来也更简单。

内容的提问来源于stack exchange,提问作者Bernd M.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:29:06