所谓 jQuery 插件,怎样开发一个 jQuery 插件

简单来说,所谓 jQuery 插件就是扩展在 jQuery 原型对象上的一个方法。通过扩展 jQuery 对象,每次调用 jQuery 对象的时候,对象里面都包含了我们自己所添加的那个方法。

一般插件的设计目的都是为了能在选择器所选择的结果集上做某些事情,本质上和 jQuery 自带的fadeOutaddClass 之类的方法没什么区别。

制作好自己的插件后,可以在自己的项目中私用,如果你愿意的话,也可以免费公开给其它人使用。而且,现在互联网上的免费插件也非常的多。另外,制作一个属于自己的 jQuery 插件的门槛真的很低。

如何制作一个插件

一个典型的插件制作方法如下:

(function($){
    $.fn.myNewPlugin = function() {
        return this.each(function(){
            // do something
        });
    };
}(jQuery));

不要被上面的代码迷惑,制作 jQuery 插件的关键点就是扩展 jQuery 的原型对象,其实也就是下面这行代码:

$.fn.myNewPlugin = function() { /* do something */ }

然后再将其封装在一个自执行函数中:

(function($){
    //...
}(jQuery));

其实也就是创建一个私有的作用域来扩展 jQuery,在这个作用域中可以随意使用 $ 符号,而不用担心和其它 JavaScript 库中的 $ 产生冲突。

所以,真正意义上的插件代码就是以下部分:

$.fn.myNewPlugin = function() {
    return this.each(function(){
        // do something
    });
};

其中的 this 关键字,指向的是调用这个插件的 jQuery 对象。

var somejQueryObject = $('#something');

$.fn.myNewPlugin = function() {
    alert(this === somejQueryObject);
};

somejQueryObject.myNewPlugin(); // alerts 'true'

一个典型的 jQuery 对象通常包含许多 DOM 元素,所以说 jQuery 对象也被看做是 DOM 对象集。因此,如果要对对象集中的每个元素作处理,就要借助于 jQuery 的 each() 方法:

$.fn.myNewPlugin = function() {
    return this.each(function(){

    });
};

和其它大多数 jQuery 方法一样,jQuery 的 each() 方法返回的也是一个 jQuery 对象,所以我们才可以使用 $(...).css().attr()... 这种广受喜爱的链式操作。为了使我们的插件也支持链式操作,插件也要返回 jQuery 对象。通过 each() 方法,可以对 jQuery 结果集中的 DOM 元素逐个进行处理,下面是个示例:

(function($){
    $.fn.showLinkLocation = function() {
        return this.filter('a').each(function(){
            $(this).append(
                ' (' + $(this).attr('href') + ')'
            );
        });
    };
}(jQuery));

// Usage example:
$('a').showLinkLocation();

此小插件的功能就是将每个超链接的地址,在超链接后面也显示出来:

<!-- 插件调用前: -->
<a href="page.html">Foo</a>

<!-- 插件调用后: -->
<a href="page.html">Foo (page.html)</a>

其实,这个插件的代码还可以再优化一下:

(function($){
    $.fn.showLinkLocation = function() {
        return this.filter('a').append(function(){
              return ' (' + this.href + ')';
        });
    };
}(jQuery));

我们使用一个匿名的回调函数作为 append 方法的参数,并且这个回调函数的返回值即为超链接的地址,和上面例子中使用 attr 方法不一样,此示例中使用了 DOM 内置的 API,通过元素的 href 属性来取得相关的值。

这里还有另外一个插件的例子,这个例子中并没有使用 each() 做循环,而是直接调用了 jQuery 的其它方法:

(function($){
    $.fn.fadeInAndAddClass = function(duration, className) {
        return this.fadeIn(duration, function(){
            $(this).addClass(className);
        });
    };
}(jQuery));

// Usage example:
$('a').fadeInAndAddClass(400, 'finishedFading');

什么时候才需要自己写插件

有时候我们需要用一小段代码实现某功能,并且这个功能在其它很多地方都可能被复用,那么这时可以考虑将这个功能写成插件。

大多数插件都仅仅是在 $.fn 命名空间下添加方法而已,jQuery 确保在此方法中使用的 this 都是指向调用该方法的 jQuery 对象。反过来,编写插件的时候,也要确保插件方法返回的也是这个对象。

下面又是一个简单的 jQuery 插件示例:

// 定义插件
(function($){
    $.fn.hoverClass = function(c) {
        return this.hover(
            function() { $(this).toggleClass(c); }
        );
    };
})(jQuery);

// 调用插件
$('li').hoverClass('hover');

要想了解更多关于 jQuery 插件开发的方法,可以参考 Mike Alsup 撰写的 A Plugin Development Pattern 一文,文中详细介绍了一款名为 $.fn.hilight 插件的开发方法。

该插件的设计模式如下:

//
// create closure
//
(function($) {
  //
  // plugin definition
  //
  $.fn.hilight = function(options) {
    debug(this);
    // build main options before element iteration
    var opts = $.extend({}, $.fn.hilight.defaults, options);
    // iterate and reformat each matched element
    return this.each(function() {
      $this = $(this);
      // build element specific options
      var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
      // update element styles
      $this.css({
        backgroundColor: o.background,
        color: o.foreground
      });
      var markup = $this.html();
      // call our format function
      markup = $.fn.hilight.format(markup);
      $this.html(markup);
    });
  };
  //
  // private function for debugging
  //
  function debug($obj) {
    if (window.console && window.console.log)
      window.console.log('hilight selection count: ' + $obj.size());
  };
  //
  // define and expose our format function
  //
  $.fn.hilight.format = function(txt) {
    return '<strong>' + txt + '</strong>';
  };
  //
  // plugin defaults
  //
  $.fn.hilight.defaults = {
    foreground: 'red',
    background: 'yellow'
  };
//
// end of closure
//
})(jQuery);

如果有兴趣,可至原文深度阅读。

via http://jqfundamentals.com/#chapter-8

Posted on 2012-03-12

No Comments

Leave a Comment