当前位置:嗨网首页>书籍在线阅读

22-讨论

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

9.5.3 讨论

1.一个示例

现在,将创建一个简单的幻灯片插件。我将在自己的一个现有插件 jQuery.SerialScroll [4]基础上建立这个插件。我在编写这个插件时第一次想到这种方法,老实说,它工作得不错。

将自己的插件命名为 slideshow 。它接收一个 <img> 元素和一个URL数组,然后循环显示这些图片。能够移动到上一张/下一张图片,跳转到某张图片,也可以自动循环显示。

从基础的功能开始:

(function( $ ){
   $.fn.slideshow = function(options){
     return this.each(function(){
        var $img = $(this),
          current = 0;
        // 添加幻灯片演示行为...
     });
   };
})( jQuery );

现在,将添加几个局部函数,使我们能转移到集合中的不同图片(URL):

function show( index ){
   var total = options.images.length;
   while( index < 0 )
     index += total;
   while( index >= total )
     index−= total;
   current = index;
   $img.attr('src', options.images[index]);
}
function prev(){
   show( current−1 );
}
function next(){
   show( current + 1 );
}

可以用事件提供这些功能:

$img.bind('prev', prev).bind('next', next).bind('goto',function(e, index){
   show( index );
});

自动循环怎么做?再添加几个函数:

var auto = false, id;
function start(){
   stop();
   auto = true;
   id = setTimeout(next, options.interval || 2000);
}
function stop(){
   auto = false;
   clearTimeout(id);
}

下面是事件:

$img.bind('start', start).bind('stop', stop);

现在需要在 show() 中添加几行,在必要时保持自动循环:

function show( index ){
   //和以前一样…
   if( auto )
     start();
}

这就可以了!现在有了具备后退、前进和自动循环功能的完整幻灯片演示程序。

为了清晰地说明这个示例,我使这个插件完全依赖于外部操纵。

下面是一个具体实现的模型:

<ul>
   <li><img id="prev" src="prev.png" /></li>
   <li><img id="slideshow" /></li>
   <li><img id="next" src="next.png" /></li>
 </ul>
...
(function( $ ){
   var $image = $('#slideshow');
   $image.slideshow({
     images: ['1.jpg', '2.jpg', '3.jpg', '4.jpg'],
     interval: 3000
   });
   $('#prev').click(function(){
     $image.trigger('prev');
   });
   $('#next').click(function(){
     $image.trigger('next');
   });
   $image.trigger('goto', 0); // 初始化为0
   $image.trigger('start'); // 我们打算自动循环显示
})( jQuery );

注意

这是使用 trigger() 是因为它很简短,事实却是,如果使用 triggerHandler() 可能会更快,因为 trigger() 将产生事件冒泡(从jQuery 1.3起),而你可能并不需要这种功能。

2.如果元素已经有其中一个事件会发生什么?

可能发生一种情况(尽管这很奇怪): #slideshow 元素可能已经绑定了名为 prevnextgotostart 或者 stop 的事件。

如果出现这种情况,解决方案见秘诀8.4。

3.如何允许其他代码清理添加的事件处理程序?

因为没有提供绑定的函数,所以其他外部代码无法解除它们的绑定。

在大部分情况下,可以简单地从事件中解除所有事件的绑定,例如:

jQuery('#slideshow').unbind('prev next goto start stop'); // 列举所有事件
//或者
jQuery('#slideshow').unbind(); //盲目地删除所有绑定

如果你需要谨慎地进行绑定解除,或者只是想要解除所有相关事件的绑定,查阅秘诀8.3。

4.与其他方法有何区别

现在还有其他的技术能够实现外部操纵。我将对其中一些进行比较:

允许插件接受命令 。jQuery UI(以及其他一些插件)使用这种模式。

这种模式就是当插件接受一个字符串作为第一个参数时执行操作,例如:

jQuery('#image').slideshow('goto', 1);

这种写法比使用事件的方法短一些,但是要求你用公开的方法保存所有必需的数据(在例子中是当前索引),以便后续的数据获取。利用这种模式的人也倾向于使用 date() 存储这些变量。

如果使用事件,可以简单地使用局部变量,因为事件处理程序可以访问插件的局部作用域。

返回带有方法的对象 。Jörn Zaefferer的 validate 插件(以及其他的一些插件)使用这种模式。

根据编码方式,对象的方法可能访问局部变量。为此必须使用闭包[5],而闭包是不能滥用的。而且,需要在某个地方(以全局方式)存储这个对象,还要求进行伪面向对象编码(你可能喜欢这种方式,也可能不喜欢)。

可以混合使用这两种方法以及前面介绍过的方法。可以创建一个对象(使用 jQuery.listener )并绑定事件然后返回对象,而不是将事件( prevnext 等)。绑定到DOM元素。正如我们在秘诀9.2中所看到的,这个监听器对象不仅限于事件。它可以拥有方法甚至在其属性中存储事件数据。