jQuery插件开发结构

Posted haliofwu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jQuery插件开发结构相关的知识,希望对你有一定的参考价值。

1,开始

可以通过为jQuery.fn增加一个新的函数来编写jQuery插件。属性的名字就是你的插件的名字:

    jQuery.fn.myPlugin = function()  
        //开始写你的代码吧!  
    ;  

但是,那惹人喜爱的美元符号 jQuery使 哪 里 去 了 ? 她 就 是 j Q u e r y , 但 是 为 了 确 保 你 的 插 件 与 其 他 使 用 的库不冲突,最好使用一个立即执行的匿名函数,这个匿名函数的参数是jQuery,这样其他的库就可以放心的使用$符号了。

 (function( $ )  
      $.fn.myPlugin = function()   

        // 开始吧!  

      ;  
    )( jQuery )

这样更好了就。在闭包内,可以放心的使用$符号了~
2,上下文

现在已经可以编写我们的代码了,但是编写之前,我必须说一说上下文。在插件内部的范围中,this关键字指向的是jQuery对象。人们很容易误解这一点,因为在正常使用jQuery的时候,this通常指向的是一个DOM元素。不了解这一点,会经常使用$又包装了一次。

 (function( $ )  

      $.fn.myPlugin = function()   

        // 没有必要使用$(this)  

        // $(this) 跟 $($('#element'))是一样的  

        this.fadeIn('normal', function()  

          //这里的this指的就是一个DOM元素了  

        );  

      ;  
    )( jQuery );  

    $('#element').myPlugin();  

3,基本开发

(function( $ )  

      $.fn.maxHeight = function()   

        var max = 0;  

        this.each(function()   
          max = Math.max( max, $(this).height() );  
        );  

        return max;  
      ;  
    )( jQuery );  
var tallest = $('div').maxHeight();

这是一个简单的插件,通过调用height()返回页面上height最大的div的height。
4,维护链式开发的特性

上一个例子是返回了一个整数,但是大多数情况下,一个插件紧紧是修改收集到的元素,然后返回这个元素让链条上的下一个使用。这是jQuery设计的精美之处,也是jQuery如此流行的原因之一。为了保证可链式,你必须返回this。

(function( $ )  

      $.fn.lockDimensions = function( type )     

        return this.each(function()   

          var $this = $(this);  

          if ( !type || type == 'width' )   
            $this.width( $this.width() );  
            

          if ( !type || type == 'height' )   
            $this.height( $this.height() );  
            

        );  

      ;  
    )( jQuery );  
 $('div').lockDimensions('width').css('color','red');  

因为该插件返回了this,所以保证了可链式,从而可以继续使用jQuery方法进行修改,如css()。如果你的插件如果不是返回一个简单值,你通常应该返回this。而且,正如你可能想到的,你传进去的参数也可以在你的插件中访问。所以在这个例子中,可以访问到type。
5,默认值和选项

为了一些复杂的,可订制的插件,最好提供一套默认值,在被调用的时候扩展默认值。这样,调用函数的时候就不用传入一大堆参数,而是传入需要被替换的参数。你可以这样做:

(function( $ )  

      $.fn.tooltip = function( options )     

        var settings =   
          'location'         : 'top',  
          'background-color' : 'blue'  
        ;  

        return this.each(function()           
          // 如果存在选项,则合并之  
          if ( options )    
            $.extend( settings, options );  
            

          // 其他代码咯  

        );  

      ;  
    )( jQuery );  
$('div').tooltip('location':'left'); 

重点内容

在这个例子中,调用插件后,默认的location会被替换城’left’,而background-color还是’blue’。这样可以保证高度可配置性,而不需要开发者定义所有可能的选项了。
6,命名空间

正确的命名空间对于插件开发十分重要,这样能确保你的插件不被其他插件重写,也能避免被页面上其他代码重写。命名空间可以使你更长寿,因为你能记录你自己的方法,事件,数据等。
a,插件方法

在任何情况下,都不要在一个插件中为jQuery.fn增加多个方法。如:


    (function( $ )  

      $.fn.tooltip = function( options )  // 这样 ;  
      $.fn.tooltipShow = function( )  // 是   ;  
      $.fn.tooltipHide = function( )  // 不好的  ;  
      $.fn.tooltipUpdate = function( content )  // 同学!  ;  

    )( jQuery ); 

不推荐这样使用,搞乱了$.fn命名空间。要纠正之,你可以把所有的方法放进一个对象中,然后通过不同的参数来调用。


    (function( $ )  

      var methods =   
        init : function( options )  // THIS ,  
        show : function( )  // IS   ,  
        hide : function( )  // GOOD ,  
        update : function( content )  // !!!   
      ;  

      $.fn.tooltip = function( method )   

        // Method calling logic  
        if ( methods[method] )   
          return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));  
         else if ( typeof method === 'object' || ! method )   
          return methods.init.apply( this, arguments );  
         else   
          $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );  
              

      ;  

    )( jQuery );  
 $('div').tooltip(  // calls the init method  
      foo : 'bar'  
    );  
    $('div').tooltip('hide'); // calls the hide method  
    $('div').tooltip('update', 'This is the new tooltip content!'); // calls the update method  

jQuery自己的扩展也是使用这种插件结构。
b,事件

绑定事件的命名空间是比较不为人知的。如果你的插件绑定了某个事件,最好将它搞到一个命名空间中。这样,如果你以后需要解绑,就不会影响到其他绑定到这个事件上的函数了。你可以使用”.”来增加命名空间。

 (function( $ )  

      var methods =   
         init : function( options )   

           return this.each(function()  
             $(window).bind('resize.tooltip', methods.reposition);  
           );  

         ,  
         destroy : function( )   

           return this.each(function()  
             $(window).unbind('.tooltip');  
           )  

         ,  
         reposition : function( )  // ... ,  
         show : function( )  // ... ,  
         hide : function( )  // ... ,  
         update : function( content )  // ...  
      ;  

      $.fn.tooltip = function( method )   

        if ( methods[method] )   
          return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));  
         else if ( typeof method === 'object' || ! method )   
          return methods.init.apply( this, arguments );  
         else   
          $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );  
              

      ;  

    )( jQuery );  

    $('#fun').tooltip();  
    // Some time later...  
    $('#fun').tooltip('destroy');  

在这个例子中,tooltip在init方法中初始化,它将reposition方法绑定到window对象的resize事件的tooltip名字空间下。稍候,如果开发者需要去掉这个tooltip,我们可以解绑这个绑定。这样就不会影响到其他绑定到window对象的resize事件的方法了。
c,数据

在开发插件的时候,你通常会有保持状态或者检查你的插件是否已经初始化的需要。使用jQuery的data方法是保持变量的很好的方法。但是,我们不把变量单独保存,而是放在一个对象中,这样就可以在一个名字空间下统一访问了。

(function( $ )  

      var methods =   
         init : function( options )   

           return this.each(function()  

             var $this = $(this),  
                 data = $this.data('tooltip'),  
                 tooltip = $('<div />',   
                   text : $this.attr('title')  
                 );  

             // If the plugin hasn't been initialized yet  
             if ( ! data )   

               /* 
                 Do more setup stuff here 
               */  

               $(this).data('tooltip',   
                   target : $this,  
                   tooltip : tooltip  
               );  

               
           );  
         ,  
         destroy : function( )   

           return this.each(function()  

             var $this = $(this),  
                 data = $this.data('tooltip');  

             // Namespacing FTW  
             $(window).unbind('.tooltip');  
             data.tooltip.remove();  
             $this.removeData('tooltip');  

           )  

         ,  
         reposition : function( )  // ... ,  
         show : function( )  // ... ,  
         hide : function( )  // ... ,  
         update : function( content )  // ...  
      ;  

      $.fn.tooltip = function( method )   

        if ( methods[method] )   
          return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));  
         else if ( typeof method === 'object' || ! method )   
          return methods.init.apply( this, arguments );  
         else   
          $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );  
              

      ;  

    )( jQuery );  

使用data方法可以帮助你在插件的各个方法间保持变量和状态。将各种变量放在一个对象中,可以方便访问,也可以方便移除。
7,总结与最佳实践

编写jQuery插件可以充分利用库,将公用的函数抽象出来,“循环利用”。以下是简短的总结:

  1. 使用(function($)//plugin)(jQuery);来包装你的插件
  2. 不要在插件的初始范围中重复包裹
  3. 除非你返回原始值,否则返回this指针来保证可链式
  4. 不要用一串参数,而是使用一个对象,并且设置默认值
  5. 一个插件,不要为jQuery.fn附上多个函数
  6. 为你的函数,事件,数据附着到某个命名空间

以上是关于jQuery插件开发结构的主要内容,如果未能解决你的问题,请参考以下文章

Jquery地址插件:如何避免历史更改?

JQuery 访问插件中的变量

Vuejs - 啥时候应该初始化 jquery 插件

jQuery livequery 插件的替代品?

编写优秀jQuery插件的10个技巧

10条建议帮助你创建更好的jQuery插件