使用带有无线电列表过滤器的jQuery fadeIn / fadeOut,但是重复两次而不是一次

时间:2013-03-20 16:49:22

标签: jquery

我正在制作一个包含游戏列表的页面。我添加了按类型过滤游戏的单选按钮。当用户点击类型过滤器时,我正在使用jQuery优雅地淡入淡出游戏列表。

问题在于,每次单击单选按钮时,游戏列表都会笨拙地淡入和淡出两次。请参阅:http://jsfiddle.net/animeguy99/pZKda/1/

以下是我使用的脚本:

$('input[name$="group1"]').click(function(){
    var radio_value = $(this).val();    
    if(radio_value=='Adventure') {
      $('#games div').fadeOut('slow', function(){
            $('#games .adv').fadeIn();
      });
    }
    else if(radio_value=='Puzzle') {
      $('#games div').fadeOut('slow', function(){
            $('#games .puz').fadeIn();
      });
    }
    else if(radio_value=='Shooter') {
      $('#games div').fadeOut('slow', function(){
            $('#games .sho').fadeIn();
      });
    }
    else if(radio_value=='All') {
      $('#games div').fadeOut('slow', function(){
            $('#games div').fadeIn();
      });
    }
});

我有DIV类声明的类型类型。因此,每次用户点击收音机时,我都会淡出所有DIV(游戏),然后通过DIV课程淡出所请求的流派。

当我用Google搜索时,类似的案例表明这可能是父/子问题。但我对如何将其与我的剧本联系起来感到困惑。

我在俯瞰什么?

5 个答案:

答案 0 :(得分:1)

.fadeOut().fadeIn()的回调函数无法按照多个元素褪色时的预期方式运行。回调不只调用一次,而是调用每个元素

如果您在其中一个console.log()回调中发出.fadeOut()来电,您会看到它被多次记录。 (Chrome开发人员工具会将其折叠为单个日志条目,左侧有一个数字。)

http://jqapi.com/#p=fadeOut

  

回调函数

     

如果提供,则动画完成后将触发回调。这对于按顺序将不同的动画串联在一起非常有用。回调不会发送任何参数,但这被设置为动画的DOM元素。如果动画了多个元素,请务必注意每个匹配元素执行一次回调,而不是整个动画执行一次。

     

从jQuery 1.6开始,.promise()方法可以与deferred.done()方法结合使用,在所有匹配元素完成动画时,为整个动画执行单个回调(参见示例for .promise())。

以下是使用.promise()删除重复回调的代码版本。它还包含了j08691的建议,即从fadeOut中排除你将要消失的元素:

var groups = {
    Adventure: '.adv',
    Puzzle: '.puz',
    Shooter: '.sho',
    All: 'div'
};

function fade( group ) {
    $('#games div')
        .not(group)
        .fadeOut()
        .promise()
        .done( function() {
            console.log( group );
            $('#games ' + group).fadeIn();
        });
}

$('input[name$="group1"]').click(function () {
    fade( groups[ $(this).val() ] );
});

通过将重复代码组合到单个函数中,此代码也比原始代码大大简化。最后,我离开了console.log()来查看正在进行的调用。

还有一些关于HTML的评论:除非你正在编写XHTML,否则你不需要使用<br />,我希望你没有这样做。 <br>没问题。更重要的是,您应该在单选按钮标签上使用<label>标签,以便整个标签可以点击:

<label><input type="radio" name="group1" value="All" checked>Show All</label><br>
<label><input type="radio" name="group1" value="Adventure">Adventure</label><br>
<label><input type="radio" name="group1" value="Puzzle">Puzzle</label><br>
<label><input type="radio" name="group1" value="Shooter">Shooter</label>

这是一个updated jsfiddle

此处还有其他简化机会。是否要求单选按钮中的value属性为特定字符串'All','Adventure'等?如果没有,您可以直接将组选择器放在value属性中:

<label><input type="radio" name="group1" value="div" checked>Show All</label><br>
<label><input type="radio" name="group1" value=".adv">Adventure</label><br>
<label><input type="radio" name="group1" value=".puz">Puzzle</label><br>
<label><input type="radio" name="group1" value=".sho">Shooter</label>

然后将JavaScript代码简化为:

function fade( group ) {
    $('#games div')
        .not(group)
        .fadeOut()
        .promise()
        .done( function() {
            console.log( group );
            $('#games ' + group).fadeIn();
        });
}

$('input[name$="group1"]').click(function () {
    fade( $(this).val() );
});

Latest jsfiddle

另一个更新......正如Alex在评论中指出的那样,当您在Show All和特定类型之间来回点击时,此版本的代码会导致块跳转。

这是由代码中的这一行引起的:

        .not(group)

删除该行可以提供更平滑的过渡,如updated jsfiddle所示。

答案 1 :(得分:1)

试试这个小提琴。 问题出在您的jQuery Selector $('#games div')上。您的选择指向多个DOM元素。因此,它将为范围中的每个元素运行fadeOut(),然后对每个运行fadeIn()的元素运行回调。添加额外的选择器将确保它只运行一次。

$('#games div').filter(":visible")

添加.filter(":visible")限制将确保只有那些可见的应该被淡出(如果不使用过滤器,那么如果隐藏选择的任何元素,它将立即触发fadeIn()) 。此外,它还将确保fadeIn()仅在选择中可见的所有元素现在都隐藏后才会运行。

jsfiddle

答案 2 :(得分:0)

你需要首先淡出元素组(通过类似.not('.puz')之类的东西),否则jQuery会首先使它们再次可见,然后淡出它们。试试这个(为了清晰起见,添加了延迟):

$('input[name$="group1"]').click(function () {
    var radio_value = $(this).val();
    if (radio_value == 'Adventure') {
        $('#games div').not('.adv').fadeOut(3000,function () {
            $('#games .adv').fadeIn(3000);
        });
    } else if (radio_value == 'Puzzle') {
        $('#games div').not('.puz').fadeOut(3000,function () {
            $('#games .puz').fadeIn(3000);
        });
    } else if (radio_value == 'Shooter') {
        $('#games div').not('.sho').fadeOut(3000,function () {
            $('#games .sho').fadeIn(3000);
        });
    } else if (radio_value == 'All') {
        $('#games div').fadeOut(3000, function () {
            $('#games div').fadeIn(3000);
        });
    }
});

<强> jsFiddle example

答案 3 :(得分:0)

问题是当你在几个元素上调用fadeOut时,会多次调用它。并且触发fadeIn的回调被调用相同的次数。你不需要那个。只有在完成所有fadeOuts时才需要开始调用fadeIn。

其中一种方法是使用$ .when .. $ done sequence:

$.when(
   $('#games div').fadeOut('slow');

).done(function() {
   $('#games .adv').fadeIn();
});

http://api.jquery.com/jQuery.when/
http://api.jquery.com/deferred.done/

答案 4 :(得分:0)

如果使用html5数据类型属性,则操作简单。结帐jsfiddle