jQuery只执行最后一个事件

时间:2015-08-23 14:51:51

标签: jquery javascript-events

刚果有1000万个问题!

我有一个包含行的表> 200。 我搜索表行中的特定文本,如果文本存在(作为行中的子字符串),我遍历行并使它们可见。如果文本不存在,我会使它们不可见。我在text-field上使用输入监听器来检测键入的文本:

$(document).ready(function () { //bind when DOM ready
    $('[name="token_search"]').on("input", function (evt) { //listener on textfield
        if ($(this).val() == "") { //if no text-show all rows
            $(".tokens-table tr").show();
            return;
        } else { //filter rows based on typed text
            $(".tokens-table tr").each(function (index) {
                if (index > 1) //do not hide first two rows
                    if ($(this).children()[0].innerHTML.indexOf($('[name="token_search"]').val()) != -1) {
                        $(this).show();
                    } else {
                        $(this).hide();
                    }
            });
        }
    });
});

当用户键入文本时,该方法将对>上的每个输入事件进行子字符串搜索。 200项。当用户键入太快或在低端设备上时,这会导致UI被挂起。如何修改上面的代码,仅针对搜索字段上的最后一个输入事件执行,而不是对队列中的所有输入事件执行?我的意思是一旦用户键入一个新字符,我就希望清除队列中的所有先前事件。

2 个答案:

答案 0 :(得分:3)

基本上你需要使用一个计时器来等待用户停止输入一段时间,然后调用你的函数。并且你应该在你的代码中多次使用它们时缓存元素和值,正如charlietfl指出的那样。以下应该可以解决问题。:

老实说,如果您的目的是创建一个过滤表格的搜索框,您可能需要查看DataTables,它可以很好地完成过滤等工作。



 $(document).ready(function() { //bind when DOM ready
   $('[name="token_search"]').on("keyup", function(evt) { //listener on textfield
     var $this = $(this);
     var value = $this.val(); // incorporated charlietfl's improvements
     // cache the value of the search input and this
     delay(function() {
       $(".tokens-table tr:gt(1)").each(function(index, element) {
         var $element = $(element);
         $this.val() == "" || $element.children()[0].innerHTML.indexOf(value) != -1 ? $element.show() : $element.hide();
       });
     }, 700); // waits till the user has stopped typing for 7/10 of a second, adjust as needed
     // 1000 = 1 second
   });
 });

 var delay = (function() {
   var timer = 0;
   return function(callback, ms) {
     clearTimeout(timer);
     timer = setTimeout(callback, ms);
   };
 })();

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="token_search" id=""><br><br>
    
    <table class="tokens-table">
        <tr>
            <td>unfilterable row</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>unfilterable row</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>one</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>two</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>one</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>four</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>one</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>three</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>two</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>one</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>three</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
        <tr>
            <td>one</td>
            <td>some data</td>
            <td>some data</td>
        </tr>
    </table>
    
&#13;
&#13;
&#13;

答案 1 :(得分:2)

代码中一个非常昂贵的部分是在每次迭代中搜索dom,以获取事件处理程序本身内已有的input的值。

执行一些值和jQuery对象的缓存。

这段代码非常昂贵:

 .... indexOf($('[name="token_search"]').val())

相反:

 $('[name="token_search"]').on("keyup", function (evt) { 
      var  value = this.value;
      if (value)...
       ....

          .... indexOf(value)

这将删除100个DOM搜索相同的值

同样,如果您对同一$(this)多次使用this,请将其缓存为变量

$(".tokens-table tr").each(function (index) {
     var $this = $(this);
     if ($this.children()[0].innerHTML.indexOf(value) != -1) {
        $this.show();
     }
});

如果这些改进无效,那么您还可以实施其他解决方案,例如throttlingdebouncing使用计时器搜索之间的时间