2

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>

スピードアップするためにできることはありますか?私はこの機能がとても気に入っていて、できればサイトに残しておきたいと思っています。

4

6 に答える 6

3
  1. jQuery は通常の JS よりも低速です。利点はクロスブラウザーのサポートですが、オブジェクトのループなどには必要ありません

  2. 各反復のループ内で同じ正規表現パターンを作成しています。外で一度宣言する

  3. 毎回 DOM をトラバースするよりも、テーブルのコピーをメモリに保持してそこで検索する方が高速です。つまり、データを多次元配列に保持し、それをスキャンします。次に、テーブルビューを更新します

  4. これを行うdataTablesという jQuery プラグインがすでにあります。

于 2013-10-28T14:18:05.297 に答える
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");} 
}

ここに画像の説明を入力

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>
于 2013-10-28T15:23:32.217 に答える
1

あなたのコードが現在遅いことは間違いありません。あなたの検索アルゴリズムは DOM を多用しています。キーボードのキーを押すたびに、セレクターからノードのリストを取得しますが、これは非常に悪い考えです。Web アプリケーションで DOM ノードへの参照を複数回取得しないでください。

DOM の外で検索したいデータを JavaScript オブジェクトに保存する必要があります。また、アンダースコアのスロットルなどを使用して、検索関数を呼び出すレートを制限することもできます。

http://underscorejs.org/#throttleを参照してください。アンダースコアを使用しない場合は、ソース コードから関数を抽出できます。

于 2013-10-28T14:25:52.280 に答える
1

検索方法をデバウンスしたい場合があります。

  1. UI の機能を維持するために非同期にする
  2. 一度に実行する検索は 1 つだけにしてください。
于 2013-10-28T14:17:56.873 に答える
0

処理時間を半分に、場合によってはそれ以上に短縮することができました。時間をテストするために window.performance.now() を使用しています。Chrome では、スクリプトはほとんど 140ms 前後で実行されていました。最長のケースは 1400ms でした。以下のスクリプトは約 50 ミリ秒から 70 ミリ秒で実行されており、検索フレーズが長いほど、スクリプトは高速に見えました (10 ミリ秒まで)。あなたの考えを教えてください(テストデータを埋めるためにループを入れました):

<!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>
于 2013-10-28T14:52:07.900 に答える
0

jQuery の組み込みの contains 関数を使用しないのはなぜですか? 私はそれを使用し、それは非常に高速です。大文字と小文字を区別しないバージョンの 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);
    });
});
于 2013-10-28T14:17:44.713 に答える