使用jQuery更快/更高效的Live Search?

时间:2015-05-18 16:00:39

标签: jquery

我有一个div列表,它们在文本输入框中有各种数据。

我有一个工作" Live Search"其中,当用户在input框中键入信息时,会对div进行过滤,直到只显示匹配的或完全没有。

但是,当行数很多时,响应速度变慢,搜索条件的输入速度很慢。

是否有更快或更有效的方法?

代码

$('input#create-row-name').keyup(function(e){
    if($(this).val()!==''){
        liveSearch();
    } else $('div#rows>div.column>div.row').show();
});

function liveSearch(){
    var searchTerm = $('input#create-row-name').val().toString().toLowerCase();
    $('div#rows>div.column>div.row').each(function(){
        var searchResult = $(this).find('div.input-group>input.row-name').val().toString().toLowerCase();
        if(searchResult.indexOf(searchTerm)>=0){
            $(this).show();
        } else $(this).hide();
    })
}

4 个答案:

答案 0 :(得分:4)

缓存值。删除关键部分中的jQuery。

var $rows = $('div#rows>div.column>div.row');
var texts = $rows.map(function () {
    return $(this).find("div.input-group > input.row-name").text().toLowerCase();
}).toArray();

$('input#create-row-name').on("keyup paste drop", function () {
    var searchTerm = $.trim( this.value.toLowerCase() ), 
        lastTerm = $(this).data("lastTerm"),
        i, found;

    if (searchTerm === lastTerm) return;
    $(this).data("lastTerm", searchTerm);

    for (i = texts.length - 1; i >= 0; i--) {
        found = searchTerm === '' || texts[i].indexOf(searchTerm) > -1;
        $rows[i].style.display = found ? "" : "none";
    }
});

绝对明智的做法是让搜索等到用户完成输入后,而不是在每个keyup事件后立即运行。我推荐debounce function like the one Sugar.js provides

另外(作为一般提示,由于缓存而在此处不那么相关):请记住,过度特定的选择器效率较低。 div#rows > div.column > div.row在计算上比 - { - 1}}更贵 - 但可能相当于 - #rows .row

答案 1 :(得分:2)

不是在每一次按键上都经过列表,而是在那里稍微延迟,这样如果有人快速连续输入多个字符,那么每次都不会这样做。 (这是几年前有人告诉我的一个技巧。)

所以,例如,像这样的东西(未经测试)......

var keyupTimer = -1;
$('input#create-row-name').keyup(function(e){
    if ($(this).val()!==''){
        if(keyupTimer != -1)
            window.clearTimeout(keyupTimer);
        keyupTimer = window.setTimeout(function(){
            liveSearch();
            keyupTimer = -1;
        },200);
    } else $('div#rows>div.column>div.row').show();
});

这将在1/5秒后运行liveSearch,足以允许普通打字员在代码完成其工作之前按几个键。

更新

正如@Halcyon评论的那样,如果计时器中运行的代码已经优化了,那么上面就好了......正如他所指出的那样,你的代码不是。

我会建议您先使用@Tomalak和@Halcyon提供的答案,而不是尝试写新内容......如果您仍然需要改进,请尝试使用我的建议。

答案 2 :(得分:1)

jQuery查找非常慢。看看你是否可以优化它们。您可以构建如下索引:

(function () {
    var index = new WeakMap();

    $('input#create-row-name').keyup(function(e){
        if($(this).val()!==''){
            liveSearch();
        } else $('div#rows>div.column>div.row').show();
    });

    // build index once initially
    $('div#rows>div.column>div.row').each(function(i, o){
        index.set(o, $(this).find('div.input-group>input.row-name'));
        // maybe even cache `.val().toString().toLowerCase()`?
    })

    function liveSearch(){
        var searchTerm = $('input#create-row-name').val().toString().toLowerCase();
        $('div#rows>div.column>div.row').each(function(i, o){
            // use index here
            var searchResult = index.get(o).val().toString().toLowerCase();
            if(searchResult.indexOf(searchTerm)>=0){
                $(this).show();
            } else $(this).hide();
        })
    }
}());

这可以显着加快您的代码速度。

答案 3 :(得分:0)

只进行基于JQuery的小改动,这就是我所得到的。

$('input#create-row-name').keyup(function(e){
    var text=$(this).val().toString().toLowerCase();
    if(text!==''){
        liveSearch(text);
    } else $('div#rows>div.column>div.row').show();
});

function liveSearch(searchTerm){   
    $('#rows input.row-name').each(function(){
        var searchResult = $(this).val().toString().toLowerCase();
        var $divHide=$(this).closest("div.row");
        if(searchResult.indexOf(searchTerm)>=0){
            $divHide.show();
        } else $divHide.hide();
    })
}

我所做的改动是

  • 在功能防御之间重复使用文本框值。
  • 优化选择器为reduce specificity
  • 直接循环遍历所有输入以查找值,然后查找并隐藏相应的父级,而不是循环划分Div并扫描其中的值
  • 可以说我在地方缓存了值

其他更好的答案出现了,因为我正在输入这个,我建议他们超过我的。我只是想提交我的解决方案。