4.5.2 处理多组元素

4.5.2 处理多组元素

与一组元素的情况不同,当为不同组的元素应用效果时,这些效果几乎会同时发生。为了示范这种并发的效果,我们可以在向上滑出一个段落时,向下滑入另一个段落。首先,要用到示例文档中的如下三、四段文本:
接着,为了更清楚地看到效果发生期间的变化,我们为第三段和第四段分别添加1像素宽的边框和灰色的背景。同时,在DOM就绪时立即隐藏第4段,参见代码清单4-23。

1
2
3
4
$(document).ready(function() { 
$('p').eq(2).css('border', '1px solid #333');
$('p').eq(3).css('backgroundColor', '#ccc').hide();
});

这样,示例文档会显示开始的段落,然后是read more链接和带边框的段落,如图4-11所示。
最后,为第三段添加click处理程序,以便单击它时会将第3段向上滑(最终滑出视图) ,同时将第4段向下滑(最终滑入视图),参见代码清单4-24。
通过截取到的这两个滑动效果变化过程中的屏幕截图,如图4-12所示,可以证实,它们确实是同时发生的。
原来可见的第三个段落,正处于向上滑到一半的状态;与此同时,原来隐藏的第四个段落,正处于向下滑到一半的状态。
排队回调函数
为了对不同元素上的效果实现排队,jQuery为每个效果方法都提供了回调函数。同我们在事件处理程序和.queue()方法中看到的一样,回调函数就是作为方法的参数传递的一个普通函数。在效果方法中,它们是方法的最后一个参数。
当使用回调函数排队两个滑动效果时,可以在第3个段落滑上之前,先将第4个段落滑下。首先,我们看一看怎样通过回调函数设置.slideDown()方法,如代码清单4-25所示。

1
2
3
4
5
6
7
8
9
10
$(document).ready(function() { 
$('p').eq(2)
.css('border', '1px solid #333')
.click(function() {
$(this).next().slideDown('slow', function() {
$(this).slideUp('slow');
});
});
$('p').eq(3).css('backgroundColor', '#ccc').hide();
});

不过,这里我们需要注意的是,必须搞清楚要滑上的到底是哪个段落。因为回调函数位于.slideDown()方法中,所以$(this)的环境已经发生了改变。现在,$(this)已经不再是指向.click()的第三个段落了——由于.slideDown()方法是通过$(this).next()调用的,所以该方法中的一切现在都将$(this)视为下一个同辈元素,即第四个段落。因而,如果在回调函数中放入$(this).slideUp('slow'), 那么我们最终还会把刚刚显示出来的段落给隐藏起来。
可靠地引用$(this)的一种简单方法,就是在.click()方法内部把它保存到一个变量中,比如var $ clickedItem = $(this)
这样,无论是在回调函数的外部还是内部,$clickedItem引用的都是第三个段落。使用了新变量之后的代码,参见代码清单4-26。

1
2
3
4
5
6
7
8
9
10
11
$(document).ready(function() { 
$('p').eq(2)
.css('border', '1px solid #333')
.click(function() {
var $clickedItem = $(this);
$clickedItem.next().slideDown('slow', function() {
$clickedItem.slideUp('slow');
});
});
$('p').eq(3).css('backgroundColor', '#ccc').hide();
});

这次效果中途的屏幕截图如图4-13所示,第三段和第四段同时都是可见的,而且,第四段已经完成下滑,第三段刚要开始上滑。
既然讨论了回调函数,那么就可以回过头来基于代码清单4-22解决在接近一系列效果结束时改变背景颜色的问题了。这次,我们不像前面那样使用.queue()方法,而是使用回调函数,如代码清单4-27所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$(document).ready(function() { 
$('div.label').click(function() {
var paraWidth = $('div.speech p').outerWidth();
var $switcher = $(this).parent();
var switcherWidth = $switcher.outerWidth();
$switcher
.css({position: 'relative'})
.fadeTo('fast', 0.5)
.animate({
left: paraWidth - switcherWidth
}, {
duration: 'slow',
queue: false
})
.fadeTo('slow', 1.0)
.slideUp('slow', function() {
$switcher.css({backgroundColor: '#f00'});
})
.slideDown('slow');
});
});

同前面一样,<div id="switcher">的背景颜色在它滑上之后滑下之前,变成了红色。注意,在使用交互的完成回调函数而不是.queue()时,不必在回调中调用next()