2012-11-27 56 views
3

我已经适应从一个教程,基于它们的内容过滤li元素下面的代码:提高JQuery的的性能发现

$('#_selectSearch_' + index).keyup(function() { 
     var filter = $(this).val(); 
     if(filter) { 
      $('#_selectDrop_' + index).find("li:not(:contains(" + filter + "))").slideUp(); 
      $('#_selectDrop_' + index).find("li:contains(" + filter + ")").slideDown(); 
     } else { 
      $('#_selectDrop_' + index).find("li").slideDown(); 
     } 
    }); 

代码工作得很好,但大名单的工作时很慢使浏览器在每次按键时都会停顿几秒钟。我一直在环顾四周,得出结论认为改进方法是以某种方式缓存列表,而不是直接在DOM上操作,但不知道如何实现。

+0

这是一个锻炼,或者你需要一个直播网站/项目的信息?我问,因为答案会有所不同。 – gibberish

+1

很可能slideUp和slideDown是性能问题发生的地方,而不是.find。但是,您可以使用.find + .filter或.not来优化.find。 '.find(“li”)。not(“:contains(”+ filter +“)”);' –

+0

@ChrisBurdon如果没有匹配,你想要显示所有项目。是对的吗? – Bruno

回答

1

如果您主要关注的是以下代码的性能:

  1. 缓存包含过滤器字符串的元素。
  2. 缓存li元素。
  3. 不显示或隐藏已处于该状态的元素。
  4. 使用indexOf,它非常快。
  5. 如果用户在500毫秒之外键入字母,showMatches将不会运行。
var selectSearch = $("#_selectSearch_" + index); 
var li = $("#_selectDrop_" + index + " li"); 
var currentTimeout; 

selectSearch.on("keyup", function() { 
    if(currentTimeout) { window.clearTimeout(currentTimeout) }; 
    currentTimeout = setTimeout(showMatches, 500); 

}); 

function showMatches() { 
    var txt = selectSearch.val(); 

    for(var i = 0, len = li.length; i < len; i++) { 

     var content = li[i].textContent ? li[i].textContent : li[i].innerText; 

     if(txt && content.indexOf(txt) > -1) { 
      if(li[i].style.display !== "block") { 
       li[i].style.display = "block"; 
      } 
     } else { 
      if(li[i].style.display !== "none") { 
       li[i].style.display = "none"; 
      } 
     } 
    } 
} 

拨弄400个li元素here

0
drop = $('#_selectDrop_' + index + ' li'); 
$('#_selectSearch_' + index).keyup(function() { 
    var filter = $(this).val(); 
    if(filter) { 
     drop.find(":not(:contains(" + filter + "))").slideUp(); 
     drop.find(":contains(" + filter + ")").slideDown(); 
    } else { 
     drop.slideDown(); 
    } 
}); 

Drop将被缓存一次,然后将在每个keyup中使用。另外这款采用了最小可能的find

+0

'.find' - >'.filter' –

0
$('#_selectSearch_' + index).keyup(function() { 

    var filter = $(this).val(); 

    // by combining and cacheing all the way to the li 
    // we save a lot of time, since it seems that's where you are doing 
    // all your searching from 

    var selectDrop = $('#_selectDrop_' + index + ' li'); 

    if (filter) { 
     selectDrop.not(':contains("' + filter + '")').slideUp(); 
     selectDrop.contains(filter).slideDown(); 
    } 
    else { 
     selectDrop.slideDown(); 
    } 
}); 
1

可以缓存这个元素$('#_selectDrop_' + index + ' li');

$('#_selectSearch_' + index).keyup(function() { 
    var $li = $('#_selectDrop_' + index + ' li'); 
    var filter = $(this).val(); 
    if (filter) { 
     $li.not(":contains(" + filter + ")").slideUp(); 
     $li.contains(filter).slideDown(); 
    } else { 
     $li.slideDown(); 
    } 
});​ 
+0

'.contains()'方法是jQuery用于检查一个DOM元素是否存在于另一个DOM元素中,而不是检查某些文本可以在那个元素中找到。 – Bruno

0

我给它一个带有几分修改(未经测试)版本,请:

$('#_selectSearch_' + index).on('keyup', function() { 
    var filter = this.value, 
     lis = document.getElementById('_selectDrop_' + index).getElementsByTagName('li'), 
     len = lis.length, 
     sup = 'textContent' in this; 
    if (filter.length) { 
     for (var i = len; i--) { 
      var text = sup ? lis[i].textContent : lis[i].innerText; 
      $(lis[i])[text.indexOf(filter) != -1 ? 'slideDown' : 'slideUp'](); 
     } 
    } else { 
     $(lis).slideDown(); 
    } 
});​