【问题标题】:Search through a big list fast with jQuery使用 jQuery 快速搜索大列表
【发布时间】:2010-11-28 13:21:37
【问题描述】:

我正在使用此代码搜索大约 500 li 标签。

$(function() {

    $.expr[":"].containsInCaseSensitive = function(el, i, m){
        var search = m[3];
        if (!search) return false;
        return eval("/" + search + "/i").test($(el).text());
    };  

    $('#query').focus().keyup(function(e){
        if(this.value.length > 0){
            $('ul#abbreviations li').hide();
            $('ul#abbreviations li:containsInCaseSensitive(' + this.value + ')').show();
        } else {
            $('ul#abbreviations li').show();    
        }
        if(e.keyCode == 13) {
            $(this).val('');
            $('ul#abbreviations li').show();
        }
    });

});

这里是 HTML:

<input type="text" id="query" value=""/>
<ul id="abbreviations">
<li>ABC<span>description</span></li>
<li>BCA<span>description</span></li>
<li>ADC<span>description</span></li>
</ul>

这个脚本有这么多的 li 标签非常慢。

我怎样才能让它更快,我怎样才能只搜索 li 中的 ABC 文本,而不是 span 标签(不更改 html)?

我知道现有的插件,但我需要一个像这样的小实现。

这里是所有感兴趣的人的完成代码

var abbrs = {};

$('ul#abbreviations li').each(function(i){
    abbrs[this.firstChild.nodeValue] = i;
});

$('#query').focus().keyup(function(e){
    if(this.value.length >= 2){
        $('ul#abbreviations li').hide();
        var filterBy = this.value.toUpperCase();
        for (var abbr in abbrs) {
            if (abbr.indexOf(filterBy) !== -1) {
               var li = abbrs[abbr];
               $('ul#abbreviations li:eq('+li+')').show();
            }
        }       
    } else {
        $('ul#abbreviations li').show();    
    }
    if(e.keyCode == 13) {
        $(this).val('');
        $('ul#abbreviations li').show();
    }   
});

【问题讨论】:

    标签: jquery performance optimization search list


    【解决方案1】:

    对于初学者,我会使用 new RegExp 而不是 eval,看看这是否会提高性能。

    我假设您正在动态填充 li 标签。有没有办法搜索直接填充此列表的数据结构而不是搜索 DOM 对象?如果我的假设不正确,你能不能在一开始就遍历这个列表并构建一个字符串数组,然后再进行搜索?

    编辑:这是构建字符串列表的方法

    var listTerms = [];
    
    $("ul#abbreviations li").each(function (li) {
        listTerms.push({text : li.firstChild.nodeValue, elem : li});
    });
    

    这是搜索的方法(简单的循环,没什么花哨的)

    var exp = new RegExp(text, "i");
    for(var i=0; i<listTerms.length; i++) {
        if (exp.match(listTerms[i].text)) {
            $(listTerms[i].elem).hide();
        }
    }
    

    【讨论】:

    • 我没有动态填充 li 标签。内容只是纯 HTML,仅此而已。你能举一个最后一个问题的例子吗?
    【解决方案2】:

    我不是 javascript 编码器,也不是熟悉 jquery,但不久前我遇到了类似的问题,涉及项目规范提案的 js 令人眼花缭乱的目录树。

    正则表达式显然是你的瓶颈。 javascript 没有高效的数组处理函数,而不是正则表达式的全部开销吗?在文档加载时解析 HTML 时,&lt;li&gt; 标签不是已经解析到 DOM 数组中了吗?在那些&lt;li&gt; 节点上遍历DOM 树应该很简单,将它们复制到一个数组中,然后在结果数组上使用“find_value”类型的函数来查找值。

    【讨论】:

      【解决方案3】:

      首先将所有项目缓存到一个对象中:

      var abbrs = {};
      
      $("ul#abbreviations li").each(function (i) {
          abbrs[this.firstChild.nodeValue] = this;
      });
      

      然后在您的对象中查找键入的文本:

      var li = abbrs[this.value.toUpperCase()];
      // show li, hide others
      

      更新:对于部分匹配,您必须遍历集合:

      var filterBy = this.value.toUpperCase();
      
      for (var abbr in abbrs) {
          if (abbr.indexOf(filterBy) !== -1) {
              var li = abbrs[abbr];
              // show li
          }
      }
      

      【讨论】:

      • +1 正确的想法,但这只有在 li 中的值是唯一的情况下才能正常工作。你也在做一个完全匹配。
      • 啊...部分匹配...好吧,我想添加首字母缩写词子字符串的所有排列将是一个丑陋的选择。
      • 代码中的一些错误,应该是:var abrs = {}; $('ul#abbreviations li').each(function(i){ abbrs[this.firstChild.nodeValue] = i; }); -- 如何进行部分匹配?
      【解决方案4】:

      我还发现此链接非常有用,您应该检查一下。干得好: ” Live Search a HTML List using jQuery – No Plugin Needed"

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-20
        • 1970-01-01
        • 2011-11-22
        • 2020-09-23
        • 2019-02-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多