• 什么是队列(Queue)

    让我们来试图解释一下队列是如何产生的:对于一个程序员来讲,队列就是一组相互堆叠在一起,有待一个接一个被处理的事件。举个列子,有一个浏览者将鼠标移到了一个按钮上,1/2秒后又移开了按钮区域,这时,2个事件(Event) 被触发——mouseover & mouseout。当你立即来处理这mouseover这个事件时mouseout事件已经发生了,它打乱了你当前的mouseover的处理进程。但是无论如何你肯定是忽略不了这个事件(mouseout)了,因为当时你已经深深陷入了一个既成事实的状态:mouseover事件已经结束了。此种状态下你估计会打算将所有的事件加载在一个队列里,每次只处理一个,然后再检查队列中未处理的事件,进而再完成...

    所有的effects是如何作用的以及你为什么需要有一个队列

    相似的事情总会发生,当你在处理Effects时你会面临这么一种状况:2个被触发effects它们作用在同一个对象上。script.aculo.us考虑到了这点,它采用了一些技术手段来管理这些effects。以下我们将用一些示例来解释这些细节。

    示例1——这里我们在一个文档上建立一个DIV(id="test1")对象, 并且在页面载入的时候执行以下2个effects:

    new Effect.SlideDown('test1');
    new Effect.SlideUp('test1');

    这两个effects将被并发执行,从而造成这样一个局面:一个effect想SlideDown这个DIV而另一个则想SlideUp。实际发生了什么事情呢?你除了看到页面忽闪几下外再没有其他你想要的效果出现了。类似的情况还可能发生在onclick事件时,你想通过一个onclick事件无法分别执行这两个effects,唉...我们确实是需要Effect.Queue啊!

    Effect.Queue

    前面的一些例子让你让你有了一个面对无队列的窘境的感性认识。如此局面让你有了一些动机去寻找一些方法让Effect.Queue给我们一些帮助去管理你的Effects。

    Effect.Queue是一个作用于全局范围的一个Effects数组(枚举对象),所有你想加入队列的effects将被添加到这个全局的队列中。你可能很想了解如何将一个effect加入队列,呵呵,非常简单。

    当你创建一个effect时,你需要为该effect定制几个参数,详情请参考这篇文章。第一个参数是你想创建effect所对应的DOM对象,当然,这个参数你已经很熟悉了。第二个参数是你对于该对象定制的一个options。我们以Effect.SlideDownEffect.SlideUp这对effect为例来说明:

    new Effect.SlideDown('test1');
    new Effect.SlideUp('test1', {queue:'end'});

    你看,我加入了一个queue对象,并给它赋值为“end”,这意味着该effect将在全局的effect队列中位于末尾的位置。在你不经意间,所有的effect已经添加到了队列中,当然,没有赋予定位的effects之间将是并列的优先级关系。

    让我们再来看上面的列子,这次我们得到的效果是对象先SlideDown,然后再SlideUp。此外,还有一个“front”参数用来将某个effect插入队列之前,看以下例子:

    new Effect.SlideUp('test1', {queue: 'end'});
    new Effect.SlideDown('test1', {queue: 'front'});

    同样,SlideDown将先于SlideUp发生,参数中的queue将会为需要的effect在队列中定位,稍后我们再来研究一下另一种安排队列的方式。

    Basic Effect.ScopedQueue

    在解释这个东东前,我们知道除非你定义了不同的函数作用范围,之前我们所提到的队列都是全局范围的。我们来看一个较为复杂的queue的定义方式:

    // small and easy syntax
    new Effect.SlideUp('test1', {queue:'end'});
    
    // syntax that allows for more tuning
    new Effect.SlideUp('test1', {queue: {position:'end'} });

    以上2个表达式所产生的效果是一样的。但是第二种表达方式可以让你用以下方式定义不同的作用域(另一个队列)。

    new Effect.SlideUp(
        'menu', {queue: {position:'end', scope: 'menuxscope'}}
    );
    new Effect.SlideUp(
        'bannerbig', 
        {queue: {position:'end', scope: 'bannerscope'}}
    );
    new Effect.SlideDown(
        'menu', 
        {queue: {position: 'end', scope: 'menuxscope'}}
    );

    这个“scope”参数定义了一个叫“menuscope”的独立队列。这个队列可以关联所有与menu有关的Effect。而另一个“bannerscope”的队列则能够管理banner相关的各种Effect。那不同的队列之间将会产生怎么样的队列顺序呢?还以上面的代码为例:先同时执行1和2,再当1执行完毕后接着执行3。也就是说不同队列之间的Effect为一个平行的执行顺序。

    如果你没有定义一个scope,那所有的Effect将以默认方式加入一个“global scope”中,并且这个队列能够被Effect.Queue所访问到。

    limit参数

    有些时候有太多的effects进入队列,比如当一个人频繁的将鼠标移进移出一个button的范围(每次会有2个effects在队列中产生),我们当然不能允许这种疯狂的举动发生。因此我们可以在queue中加入一个“limit:n”的参数用来控制相应队列的长度。

    new Effect.SlideDown(
        'menu', 
        {queue: {position:'end', scope:'menuxscope', limit:2}}
    ); // #1
    new Effect.Highlight(
        'menu', 
        {queue: {position:'end', scope: 'menuxscope', limit:2}}
    ); // #2
    new Effect.SlideUp(
        'menu', 
        {queue: {position: 'end', scope: 'menuxscope', limit:2}}
    );  // #3

    #1、#2将被加入“menuscope”队列,而#3则不会。

    Effect.Queues

    那什么又是Effect.Queues呢?我们将如何来利用它?实际上,在每个scope中都会产生一个scope的实例。这个实例已经被载入了Effect.Queus了。你可以用Effect.Queues.get('globel')的方式来访问它。默认的“globel queue”以被framework保存进了Effect.Queue。当然,如果你想获取一个非“globel”的队列,你可以这样来访问:Effect.Queues.get('myscope')。

    那些局部队列(ScopeQueue) 所管理的effects,将会在一个内部环境中被所作用的对象来访问,如果你愿意,你可以添加或者删除这些effects。

    局部队列是一个枚举类型的对象,你可以一个接一个的获取这些effects并且对其进行操作。让我们看下以下代码是如何清空一个队列的。

    var queue = Effect.Queues.get('myscope');
    queue.each(function(e) { e.cancel() });

    或者,你还可以改变对类中每个Effect执行之间的时间间隔

    Effect.Queues.get('myscope').interval = 100;

    (随便翻了些,不知道看得懂不,实践是关键啊!)

  • Effect.toggle

    该方法能根据当前状态切换衍生方法中的3对互补effect。

    该方法基本的表达式为:

    Effect.toggle(element, ['appear' | 'slide' | 'blind'], [options] ); 

    注意:在运用过程中的注意点和先前介绍的衍生对象本身需要注意的地方相同,例如运用slide的时候需要在指定对象外加包一层块对象等等...

  • Effect.Grow

    让对象按指定设置的方向“生长”出来。

    示例:

    Effect.Grow('id_of_element');

    该方法有一个direction参数控制对象的“生长”方式。其取值如下:

    • top-left
    • top-right
    • bottom-left
    • bottom-right
    • center

    请看代码:

    Effect.Grow('content', {direction: 'top-left'});
  • Effect.Fold

    该效果将对象先向上缩进再向左收缩,然后消失。

    示例:

    Effect.Fold('id_of_element');

    注意:该effect能作用于除table之外的块对象。

  • Effect.Shrink

    类似Effect.Grow的反向操作,将对象按指定设置的方向收缩至消失。其他详情请查看Effect.Grow