如何加快大型库存文件的javascript / jquery?

时间:2013-10-28 14:07:37

标签: javascript jquery search

我使用jquery和javascript的混合来搜索一堆项目。确切地说是5000+。我在我的网站上使用实时搜索功能,根据关键字过滤这些项目。但是因为有很多项目要搜索它,所以我想加快这个过程。

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/JavaScript">
    $(document).ready(function() {
        $("#filter").keyup(function() {

            // Retrieve the input field text and reset the count to zero
            var filter = $(this).val(), count = 0;

            // Loop through the list
            $(".inventory tr").each(function() {

                // If the list item does not contain the text phrase fade it out
                if ($(this).text().search(new RegExp(filter, "i")) < 0) {
                    $(this).fadeOut();

                    // Show the list item if the phrase matches and increase the count by 1
                } else {
                    $(this).show();
                    count++;
                }
            });

            // Update the count
            var numberItems = count;
            $("#filter-count").text("Number of items = "+count);
        });
    });
</script>

<form id="live-search" action="" class="styled" method="post">
    <fieldset>
        <input type="text" class="text-input" id="filter" value="" />
        <span id="filter-count"></span>
    </fieldset>
</form>

<div class="inventory">
    <table> Stuff </table>
</div>

我能做些什么来加快速度吗?我非常喜欢这个功能,如果可能的话,我希望将它保留在网站上。

6 个答案:

答案 0 :(得分:3)

  1. jQuery比vanilla慢;它的好处是跨浏览器 支持,但你不需要循环这样的东西 对象

  2. 你在循环中创建了相同的正则表达式模式 每次迭代;在外面宣布一次

  3. 将表的副本保存在内存中并在那里搜索会更快,而不是每次都遍历DOM。也就是说,将数据保存在多维数组中并进行扫描;然后更新表格视图

  4. 已经有一个jQuery插件可以为您执行此操作,名为dataTables

答案 1 :(得分:2)

这个小小的非jquery婴儿在大约50毫秒内解析了10000多个元素。

function foo(){
    var nodes = document.evaluate('//table[@class="inventory"]//tr', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null), 
    filterValue = document.getElementById('filter').value;

    if (nodes != null && filterValue != '') {
        var re = new RegExp(filterValue, "i"), count = 0;

        for (var m = 0; m < nodes.snapshotLength; m++){
            var item = nodes.snapshotItem(m);

            if(re.test(item.innerHTML.replace(/<(?:.|\n)*?>/gm, '').trim())){
                count++;
                item.style.display = 'block';
            } else {
                item.style.display = 'none';
            }
        }   

    }
    console.log("Parsed " + nodes.snapshotLength + " elements and matched " + count);
}


function time_my_script(script) {
    var start = new Date();
    script();
    return new Date() - start;
}

window.onload  = function() {
    var filter = document.getElementById('filter');
    filter.onkeyup=function(){ console.log("Time: " + time_my_script(foo) + "ms");} 
}

enter image description here

Html

<html>
<head>
<script type="text/javascript">
// ...
</script>
</head>
<body>

    <input type="text" id="filter" name="filter" />

    <table class="inventory">
        <tr>
            <td>axxxasd</td>
        </tr>
    </table>
    <table class="inventory">
        <tr>
            <td>axxxasd</td>
        </tr>
    </table>
    <table class="inventory">
        <tr>
            <td>axxxasd</td>
        </tr>
    </table>
    <table class="inventory">
        <tr>
            <td>asd</td>
        </tr>
    </table>
    <!-- ... -->
</body>
</html>

答案 2 :(得分:1)

您可能需要debounce搜索方法:

  1. 使其保持异步以保持UI功能
  2. 确保一次只运行一个搜索。

答案 3 :(得分:1)

我毫不怀疑您的代码目前很慢,您的搜索算法会广泛使用DOM。在键盘上的每个键上,您从选择器中检索节点列表,这是一个非常糟糕的主意,您不应该在Web应用程序中多次检索对DOM节点的引用。

您应该在javascript对象中存储要在DOM之外搜索的数据,并且您可能还需要使用下划线的限制来限制搜索函数的调用率。

请参阅:http://underscorejs.org/#throttle,如果不使用下划线,可以从源代码中提取函数。

答案 4 :(得分:0)

为什么不使用jQuery的内置包含函数?我用它而且速度很快。我使用了一个不区分大小写的contains函数版本。

$(document).ready(function () {
    // to make :contains case insensitive!!!
    $.expr[":"].contains = $.expr.createPseudo(function (arg) {
        return function (elem) {
            return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
        };
    });

    $('#filter').on('input', function () {
        var $t = $(this);
        if ($t.val()) {
            $('.inventory tr').hide();
            $('.inventory').find('tr:Contains("' + $t.val() + '")').show();
        }
        else {
            $(".inventory tr").show();
        }
         $("#filter-count").text("Number of items = " + $(".inventory tr:visible").length);
    });
});

答案 5 :(得分:0)

我能够将处理时间缩短一半,在某些情况下远远超过这个时间。我正在使用window.performance.now()来测试时间。在Chrome中,您的脚本大部分时间都在140毫秒左右。最长的病例是1400毫秒。下面的脚本运行在50ms-70ms左右,搜索短语看起来越长,脚本越快(低至10ms)。让我知道你的想法(我把循环填满测试数据):

<!DOCTYPE html>
<html>
<head>
</head>
<body>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/JavaScript">
$(document).ready(function(){
    var startTime;
    var endTime;
    var i;
    var htmlString = "";

    for(i = 0; i < 5000; i += 1){
        htmlString += "<tr class='inventory'><td>This is my test thing</td></tr>";
    }

    $('#myTable').html(htmlString);


    $("#filter").keyup(function(){
        startTime = window.performance.now();
        // Retrieve the input field text and reset the count to zero
        var filter = $(this).val(),
        count = 0,
        matchedItems = $('tr.inventory td:contains("'+filter+'")'),
        nonMatchedItems = $('tr.inventory td').not(matchedItems),
        numItems = matchedItems.length;

        matchedItems.show();
        nonMatchedItems.hide();

        $("#filter-count").text("Number of items = "+numItems);

        endTime = window.performance.now();
        console.log(endTime - startTime);
    });
});
</script>
<form id="live-search" action="" class="styled" method="post">
    <fieldset>
        <input type="text" class="text-input" id="filter" value="" />
        <span id="filter-count"></span>
    </fieldset>
</form>
<div class="inventory">
<table id="myTable"></table></div>

</body>
</html>