使用选择器加速这个 jQuery 代码

Posted

技术标签:

【中文标题】使用选择器加速这个 jQuery 代码【英文标题】:Speeding up this jQuery-code with selectors 【发布时间】:2011-05-26 17:23:09 【问题描述】:

我为许多对象的列表编写了一个过滤器。用户可以通过单选按钮选择他们的选项。

在我的过滤器功能中,我选择了两个单选组/组的选中单选按钮:

if ( $('#filter input[name="interval"]:checked').val() == 'all' ) 
    if( $('#filter input[name="day"]:checked').val() == 'all' ) 
        var searchSelector = "li";
     else 
        var searchSelector = "li[data-day=" + $('#filter input[name="day"]:checked').val() + "]";
    
 else 
    if( $('#filter input[name="day"]:checked').val() == 'all' ) 
        var searchSelector = "li[data-interval=" + $('#filter input[name="interval"]:checked').val() + "]";
     else 
        var searchSelector = "li[data-interval=" + $('#filter input[name="interval"]:checked').val() + "]" + "li[data-day=" + $('#filter input[name="day"]:checked').val() + "]";
    

正如jQuery Performance Rules 中所说,我应该缓存 jQuery 对象。通常这种做法总是有效的——但在这种情况下,我的第二个单选按钮的值总是输出第一个选中值的值。

任何想法,我可以如何简化这个 jQuery 代码?

谢谢

这是按钮的 html

<form id="filter">
    <fieldset>
        <label>
            <input type="radio" name="interval" value="all">
            all</label>
        <label>
        <label>
            <input type="radio" name="interval" value="hourly">
            hourly</label>
        <label>
            <input type="radio" name="interval" value="daily">
            daily</label>
        <label>
            <input type="radio" name="interval" value="weekly">
            weekly</label>
        <label>
            <input type="radio" name="interval" value="monthly">
            monthly</label>
        <label>
            <input type="radio" name="interval" value="yearly">
            yearly</label>
    </fieldset>
    <fieldset>
        <label>
            <input type="radio" name="day" value="all">
            all</label>
        <label>
            <input type="radio" name="day" value="monday">
            monday</label>
        <label>
            <input type="radio" name="day" value="tuesday">
            tuesday</label>
        <label>
            <input type="radio" name="day" value="wednesday">
            wednesday</label>
        <label>
            <input type="radio" name="day" value="thursday">
            thursday</label>
        <label>
            <input type="radio" name="day" value="friday">
            friday</label>
    </fieldset>
</form>

这就是我的列表的样子:

<li data-day="monday" data-interval="weekly">foo</li>
<li data-day="friday" data-interval="yearly">foo</li>

【问题讨论】:

【参考方案1】:

为什么不做这样的事情——我假设searchSelector 在代码后面被应用于.find(),因为没有定义ul 来查看...

// This may also be $("li") -- I was assuming you were using it for a .find()
var $result = $something.find("li");
// This finds "all" the possible results - now to filter we need the values:
// Use || 'all' to default to "all" if there is no "checked" filter
var interval = $('#filter input[name="interval"]:checked').val() || 'all';
var day = $('#filter input[name="day"]:checked').val() || 'all';

// if we need to filter this list at all:
if (day != 'all' || interval != 'all') 
  // store the new result of the filter
  $result = $result.filter(function() 
    // check the .data-day .data-interval attributes on this directly:
    if (day != 'all' && this.data-day != day) return false;
    if (interval != 'all' && this.data-interval != interval) return false;
    return true;
  );

我还假设您正在使用它来以某种方式切换这些&lt;li&gt; 的可见性...在第一行中,您可以将.hide() 附加到链并在此代码块的末尾调用$results.show()

【讨论】:

【参考方案2】:

以下应该做到这一点

var $interval = $('#filter input[name="interval"]'),
    $day = $('#filter input[name="day"]');

    $('#filter input:radio').change(function()
        var interval = $interval.filter(':checked').val() || 'all',
            day = $day.filter(':checked').val()|| 'all',
            searchSelector = 'li';

            searchSelector += (day != 'all') ? '[data-day=' + day  + ']' : '';
            searchSelector += (interval != 'all') ? '[data-interval=' + interval  + ']' : '';
          
        /*do what you want with the selector here*/
    );

示例:http://www.jsfiddle.net/gaby/xPMn5/

【讨论】:

您的“更简化”仍然相当复杂......为什么不:searchSelector='li'; if(day!='all') searchSelector += '[data-day='+day+']'; if (interval!='all') searchSelector += '[data-interval='+interval+']'; +1 为|| 'all' 在没有检查任何间隔/天的情况下 - 以及 $interval 和 $day 的“缓存”......虽然现在你可能想打电话他们$intervals$days 不止一个 我使用单数的意思是它是一个单一的值(虽然列表包含所有)。

以上是关于使用选择器加速这个 jQuery 代码的主要内容,如果未能解决你的问题,请参考以下文章

减少用于加速交互的jquery选择器的数量

jquery选择器中加变量参数

jQuery 类选择器性能(困惑)

02_jquery_基础选择器

带有变量的 jQuery 选择器

jquery ui 多日期选择器数据范围没有周末