`
dingchao.lonton
  • 浏览: 48677 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

用jquery如何扩展自己的插件

阅读更多

 

 Getting Started

To write a jQuery plugin, start by adding a new function property to the jQuery.fn object where the name of the property is the name of your plugin:

 

 

jQuery.fn.myPlugin = function() {

  // Do your awesome plugin stuff here

};
 

 

 

But wait! Where's my awesome dollar sign that I know and love? It's still there, however to make sure that your plugin doesn't collide with other libraries that might use the dollar sign, it's a best practice to pass jQuery to an IIFE (Immediately Invoked Function Expression) that maps it to the dollar sign so it can't be overwritten by another library in the scope of its execution.

 

 

(function( $ ) {
  $.fn.myPlugin = function() {
  
    // Do your awesome plugin stuff here

  };
})( jQuery );
 

 

 

Ah, that's better. Now within that closure, we can use the dollar sign in place of jQuery as much as we like.


Context

Now that we have our shell we can start writing our actual plugin code. But before we do that, I'd like to say a word about context. In the immediate scope of the plugin function, the this keyword refers to the jQuery object the plugin was invoked on. This is a common slip up due to the fact that in other instances where jQuery accepts a callback, the this keyword refers to the native DOM element. This often leads to developers unnecessarily wrapping the this keyword (again) in the jQuery function.

 

 

(function( $ ){

  $.fn.myPlugin = function() {
  
    // there's no need to do $(this) because
    // "this" is already a jquery object

    // $(this) would be the same as $($('#element'));
        
    this.fadeIn('normal', function(){

      // the this keyword is a DOM element

    });

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

 

The Basics

Now that we understand the context of jQuery plugins, let's write a plugin that actually does something.

 

 

(function( $ ){

  $.fn.maxHeight = function() {
  
    var max = 0;

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

    return max;
  };
})( jQuery );
var tallest = $('div').maxHeight(); // Returns the height of the tallest div
 

 

This is a simple plugin that leverages .height() to return the height of the tallest div in the page.

 

Maintaining Chainability

The previous example returns an integer value of the tallest div on the page, but often times the intent of a plugin is simply modify the collection of elements in some way, and pass them along to the next method in the chain. This is the beauty of jQuery's design and is one of the reasons jQuery is so popular. So to maintain chainability in a plugin, you must make sure your plugin returns the this keyword.

 

 

(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');
 

 

Because the plugin returns the this keyword in its immediate scope, it maintains chainability and the jQuery collection can continue to be manipulated by jQuery methods, such as .css. So if your plugin doesn't return an intrinsic value, you should always return the this keyword in the immediate scope of the plugin function. Also, as you might assume, arguments you pass in your plugin invocation get passed to the immediate scope of the plugin function. So in the previous example, the string 'width' becomes the type argument for the plugin function.

 

Defaults and Options

For more complex and customizable plugins that provide many options, it's a best practice to have default settings that can get extended (using $.extend) when the plugin is invoked. So instead of calling a plugin with a large number of arguments, you can call it with one argument which is an object literal of the settings you would like to override. Here's how you do it.

 

 

(function( $ ){

  $.fn.tooltip = function( options ) {  

    // Create some defaults, extending them with any options that were provided
    var settings = $.extend( {
      'location'         : 'top',
      'background-color' : 'blue'
    }, options);

    return this.each(function() {        

      // Tooltip plugin code here

    });

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

 

In this example, after calling the tooltip plugin with the given options, the default location setting gets overridden to become 'left', while the background-color setting remains the default 'blue'. So the final settings object ends up looking like this:

 

 

{
  'location'         : 'left',
  'background-color' : 'blue'
}
 

 

This is a great way to offer a highly configurable plugin without requiring the developer to define all available options.

 

Namespacing

Properly namespacing your plugin is a very important part of plugin development. Namespacing correctly assures that your plugin will have a very low chance of being overwritten by other plugins or code living on the same page. Namespacing also makes your life easier as a plugin developer because it helps you keep better track of your methods, events and data.

 

Plugin Methods

Under no circumstance should a single plugin ever claim more than one namespace in the jQuery.fn object.

 

 

(function( $ ){

  $.fn.tooltip = function( options ) { 
    // THIS
  };
  $.fn.tooltipShow = function( ) {
    // IS
  };
  $.fn.tooltipHide = function( ) { 
    // BAD
  };
  $.fn.tooltipUpdate = function( content ) { 
    // !!!  
  };

})( jQuery );
 

 

This is a discouraged because it clutters up the $.fn namespace. To remedy this, you should collect all of your plugin's methods in an object literal and call them by passing the string name of the method to the plugin.

 

 

(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 );

// calls the init method
$('div').tooltip(); 

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

 

This type of plugin architecture allows you to encapsulate all of your methods in the plugin's parent closure, and call them by first passing the string name of the method, and then passing any additional parameters you might need for that method. This type of method encapsulation and architecture is a standard in the jQuery plugin community and it used by countless plugins, including the plugins and widgets in jQueryUI.

 

Events

A lesser known feature of the bind method is that is allows for namespacing of bound events. If your plugin binds an event, its a good practice to namespace it. This way, if you need to unbind it later, you can do so without interfering with other events that might have been bound to the same type of event. You can namespace your events by appending “.<namespace>” to the type of event you're binding.

 

 

(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');
 

 

In this example, when the tooltip is initialized with the init method, it binds the reposition method to the resize event of the window under the namespace 'tooltip'. Later, if the developer needs to destroy the tooltip, we can unbind the events bound by the plugin by passing its namespace, in this case 'tooltip', to the unbind method. This allows us to safely unbind plugin events without accidentally unbinding events that may have been bound outside of the plugin.

 

Data

Often times in plugin development, you may need to maintain state or check if your plugin has already been initialized on a given element. Using jQuery's data method is a great way to keep track of variables on a per element basis. However, rather than keeping track of a bunch of separate data calls with different names, it's best to use a single object literal to house all of your variables, and access that object by a single data namespace.

 

 

(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 );
 

 

Using data helps you keep track of variables and state across method calls from your plugin. Namespacing your data into one object literal makes it easy to access all of your plugin's properties from one central location, as well as reducing the data namespace which allows for easy removal if need be.

 

Summary and Best Practices

Writing jQuery plugins allows you to make the most out of the library and abstract your most clever and useful functions out into reusable code that can save you time and make your development even more efficient. Here's a brief summary of the post and what to keep in mind when developing your next jQuery plugin:

  • Always wrap your plugin in a closure: (function( $ ){ /* plugin goes here */ })( jQuery );
  • Don't redundantly wrap the this keyword in the immediate scope of your plugin's function
  • Unless you're returning an intrinsic value from your plugin, always have your plugin's function return the this keyword to maintain chainability.
  • Rather than requiring a lengthy amount of arguments, pass your plugin settings in an object literal that can be extended over the plugin's defaults.
  • Don't clutter the jQuery.fn object with more than one namespace per plugin.
  • Always namespace your methods, events and data. 

 

分享到:
评论

相关推荐

    教你如何做一个自己的jQuery插件,jQuery扩展笔记

    教你如何做一个自己的jQuery插件,jQuery扩展

    简洁美观的jQuery计算器插件

    基于jQuery的计算器插件,外观简洁和美观,计算器的功能也很强大。有兴趣的同学可以继续为这款计算器扩展功能,应该也不是难事。

    jQuery 表单验证插件

    jQuery formValidator表单验证插件,它是基于jQuery类库,实现了js脚本于页面html代码的分离。你可以划分多个校验组,每个组的校验都是互不影响。对一个表单对象,你只需要写一行代码就可以轻松实现无数种(理论上)...

    Datatables jquery表格插件

    Datatables是一款jquery表格插件。它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能,包括排序、分页、扩展、主题、国际化等

    jquery插件使用方法大全

    (详情可以参见:jQuery.ajax文档) 此外,系统的可扩展性大大增强,可以附加各种数据处理器、过滤器和传输机制,为开发新的Ajax插件提供了方便。 2. 延迟对象 延迟对象(Deferred Object,jQuery.Deferred对象)是...

    jquery插件之easing使用

    具体介绍 jquery插件之easing使用,适合移动开发的js使用

    jquery.autocomplete插件修改扩展功能

    autocomplete插件原有功能,不能满足需求所以修改了增加了以下几点...4 增加插件赋值给一个隐藏域,就可以得到文本和值 (做asp.net的用起来比较方便) 博客说明 http://blog.csdn.net/spyking945/article/details/44775827

    jQuery分页插件

    一个jQuery的分页插件,是在原来网上下载的jQuery的插件上扩展的,原来的是只有按钮的,扩展新增了可以选择用文本框或下拉框来选择跳转页面。因为出现过乱码问题,所以中文的那个里面的中文字符是用的Unicode的编码

    jquery.easing插件

    jquery.easing.js 1.3 是一个配合jquery实现完美动画效果的扩展插件,比如我们在使用jquery制作一幅图片滚动或图片渐变,使用本插件可扩展或增强jquery性能,生成完美无缺兼容性更好的jquery动画来,它不仅可以用于...

    jquery扩展插件,取得包含标签自身的html

    jquery扩展插件,jquery提供的html()方法,只能获取标签内部内容,本插件进行了扩展实现了取得包含标签自身的html,并解决了input/radio/checkbox/select等输入后无法取值问题。

    Jquery UI Tabs插件扩展

    一个JqueryUI Tabs插件的扩展 可动态添加或关闭的Tabs插件 已经添加过的Tab,再次添加时候不添加新的,而是选中原来的Tab。

    jquery菜单展开插件(jqueryaccordion)

    jquery菜单展开插件,里面有插件所用到的js库,css样式,以及典型的demo,有几种展开样式的代码各供开发者扩展。可快速实现菜单展开的效果。

    Jquery扩展插件,图片异步分页浏览

    Jquery扩展插件,图片异步分页浏览 Jquery扩展插件,图片异步分页浏览

    支持dw cs5的jquery提示插件

    为Dw CS5安装jQuery代码提示扩展插件. 本资料共包含以下附件: jQuery_api_for_dwcs5.rar

    cropper头像上传jquery插件

    本Demo基于cropper插件整理的便捷源码,下载即可直接使用! 并且Demo中有详细的注释,通俗易懂,易于扩展、维护、个性化设置等! 还是那句话,谁下谁知道

    jQuery formValidator表单验证插件4.1.3提供下载

    jQuery formValidator表单验证插件,它是基于jQuery类库,实现了js脚本于页面html代码的分离。你可以划分多个校验组,每个组的校验都是互不影响。对一个表单对象,你只需要写一行代码就可以轻松实现无数种(理论上)...

    全国城市地区Jquery插件

    全国 省份 城市 地区 Jquery插件 有能力的自己扩展

    jquery 表格分页处理插件 DataTables

    DataTables是提供了大量特性的强大jQuery表格插件。例如:你可以自动轻松筛选、Ajax预读取数据、分页、列排序、高亮排序列、扩展插件支持、使用CSS或jQuery UI ThemeRoller 定制主题和完整文档。

    jquery插件flash上传

    基于jquery+flash的一个上传插件,拥有超强的自定义扩展空间。

    jQuery扩展插件和拓展函数的写法-代码

    jQuery扩展插件和拓展函数的写法---代码

Global site tag (gtag.js) - Google Analytics