最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - Is it possible to optimize Javascript client-side search? - Stack Overflow

programmeradmin6浏览0评论

Here is the jQuery/Javascript code I'm using to sort through an unordered list of elements and remove them based on the user's query:

// event binding for the search filter
$('.search-box').keyup(function(){
    var query = $(this).val().toLowerCase(),
        length = query.length;

    $('.friends-list li').each(function(){
        if(query.length > 1 && $(this).find('span').text().toLowerCase().substring(0, length) != query){
            $(this).hide();
        } else {
            $(this).show();
        }
    });
});

Unfortunately, when I get a large number of li elements, this slows down considerably and sometimes hangs on the system. Is there a way to optimize this, or do all of the searching first and then remove the li elements all at one time so the system does not hang?

When I do a server-side search, I can just have a loading spinner and a success callback, but the same does not seem to apply for the client-side.

Here is the jQuery/Javascript code I'm using to sort through an unordered list of elements and remove them based on the user's query:

// event binding for the search filter
$('.search-box').keyup(function(){
    var query = $(this).val().toLowerCase(),
        length = query.length;

    $('.friends-list li').each(function(){
        if(query.length > 1 && $(this).find('span').text().toLowerCase().substring(0, length) != query){
            $(this).hide();
        } else {
            $(this).show();
        }
    });
});

Unfortunately, when I get a large number of li elements, this slows down considerably and sometimes hangs on the system. Is there a way to optimize this, or do all of the searching first and then remove the li elements all at one time so the system does not hang?

When I do a server-side search, I can just have a loading spinner and a success callback, but the same does not seem to apply for the client-side.

Share Improve this question asked Jan 11, 2012 at 22:13 drewblaisdelldrewblaisdell 6105 silver badges16 bronze badges 1
  • 1 this just randomly popped up in my stream, great question...take an upvote! – Jesse Pollak Commented Jan 11, 2012 at 22:29
Add a ment  | 

6 Answers 6

Reset to default 4

A couple of tips

Don't fire search on each keyup event. Instead, have a short timer (~200ms) that waits for a next keyup and starts searching if there's none:

 keyup:
      clearTimeout(searchTimer)
      searchTimer = setTimeout(doSearch, 200)

If query.length <=1 your loop can be optimized away, no need to check that on each iteration.

each(li)...find(span) is too much overhead. Try iterating thru spans directly:

$('.friends-list li span').each(function() {
    var p = $(this);
    if(p.text().toLowerCase().indexOf(query) !== 0) {
        p.parent().hide();
    } else {
        p.show();
    }
});

Also note some minor optimizations in the above code.

I'd also suggest to use for loop as it's significantly faster.

Deferring DOM updates is an effective way speed up code such as this. Do them all at the end, rather than during your .each() loop.

I'd suggest a delay on the keystrokes such that you don't do the search until the user has stopped typing for some amount of time - say, half a second, though you can try that out and tweak it to taste. Plus I've made a couple of minor changes to your search, e.g., if you know the search string is too short you just want to show everything so no need to test each item in a loop in that case.

(function() {
   var timerID = null;

   function doSearch(query) {
     var length = query.length;

     if (length <= 1) {
        $('.friends-list li').show();
     } else {
        $('.friends-list li').each(function(){
           var $this = $(this);
           if($this.find('span').text().toLowerCase()
                                       .substring(0, length) != query)
              $this.hide();
           else
              $this.show();
        });
     }
   } 

   $('.search-box').keyup(function(){
      var searchString = this.value.toLowerCase();

      if (timerID)
         clearTimeout(timerID);

      timerID = setTimeout(function() {
         timerID = null;
         doSearch(searchString);
      }, 500);
   });
)();

Currently you fire a full search on every key stroke. You may want to wait a small amount of time. Say 0,2 seconds and check if another key has been pressed. The small delay should be okay for the user experience, even hardly noticeable, but if someone is typing a word (pressing keys in rapid succession) this can save you many of those iterations increasing the experienced speed.

And I know this is old, but consider better selectors, caching elements and event bubbling (not applicable here) - search for optimize jQuery and you'll get a bunch of excellent tips.

发布评论

评论列表(0)

  1. 暂无评论