你的位置:首页 > Java教程

[Java教程]jQuery插件的点点滴滴


 说起jQuery插件,很多人的脑海种已经有了一定的雏形,仿佛感觉仅仅就是那样子,事实呢?当你看了Bootstrap.js,品读了slidesjs,观摩了jquery.cycle2.js,不禁发现,原来插件的世界千变万化,细微之处总是不容易让人发觉,世界那么大,那么我们就一起去看看它到底长什么样子?

  工欲善其事必先利其器,如果你对于jQuery插件运用熟练的话,那么对已$.extend,你一定要去了解!,下面我们就先对$.extend来个剖析!先看看你对于$.extend的几种形式!

  一、$.extend的用法

1 $.extend(dest,src1,src2,src3...)2 $.extend({},src1,src2,src3...)  3 $.extend({name:function(){}})  4 $.fn.extend({name:function(){}})  5 $.extend({net:{}})  6 $.extend({boolean,dest,src1,src2,src3...})

  

  $.extend(dest,src1,src2,src3...) 

  将src1,src2,src3...合并到dest中,请记住合并时,后面同名的属性会覆盖掉前面的属性,对于前面没有的属性,难就进行合并,如下: 

<script type="text/javascript">  $(function() {    var obj = {        name: "yyh",        age: 26      },      obj1 = {        name: "yyh1",        age: 27      },      obj2 = {        name: "yyh2",        age: 27,        address:"chitu"      }    var mergeObj = $.extend(obj,obj1,obj2);    console.log(mergeObj)//{name: "yyh2", age: 27, address: "chitu"}  })</script>

  $.extend({},src1,src2,src3...) 

  这个和上面的是一样的,不同只是把dest={},把src1,src2,src3合并到一个空对象中,原理同上,不在赘述!

  

 

  $.extend({name:function(){}}) 

  看到这个东西,你可以这么认为,这是相当于$.extend(dest,src1) 中省略了dest后变成了$.extend(src1),这样子就相当于将该src合并到调用extend方法的对象中去,也就是将src合并到jquery的全局对象中去!举个例子,我们给jquery全局对象拓展一个是否支持CSS3的方法supportCSS3:

 1 <script type="text/javascript"> 2   $(function() { 3     $.extend({ 4       supportCSS3: function() { 5         var body, i, style, transition, vendor; 6         body = document.body || document.documentElement; 7         style = body.style; 8         transition = "transition"; 9         vendor = ["Moz", "Webkit", "Khtml", "O", "ms"];10         transition = transition.charAt(0).toUpperCase() + transition.substr(1);11         i = 0;12         while (i < vendor.length) {13           if (typeof style[vendor[i] + transition] === "string") {14             return vendor[i];15           }16           i++;17         }18         return false;19       }20     })21     if($.supportCSS3){22       alert("该浏览器支持css33");23     }24   })25   </script>

   所以像$.get,$post,$.ajax就是jquery全局对象的方法!

   

  $.fn.extend({name:function(){}})

  和上面的$.extend相比,如果对于js的原型对象有了解,你肯定可以知道$.fn=jQuery.prototype,也就是说这种方式是把方法拓展到jquery对象的实例中,同样来个例子:

 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4   <meta charset="UTF-8"> 5   <title>demo1</title> 6   <script src="http://libs.baidu.com/jquery/1.10.0/jquery.js"></script> 7 </head> 8 <body> 9   <button id="btn1">点击</button>10   <script type="text/javascript">11   $(function() {12     $.fn.extend({13       say: function() {14         alert("我是丑男孩");15         return this;//为什么加this,jquery的链式写法,你懂的!16       }17     });18     $("#btn1").on("click",function(){19       $(this).say().hide();20     })21 22   })23   </script>24 </body>25 </html>

  

  $.extend({net:{}})

  顾名思义,这个事在全局对象中扩展一个net命名空间,理解方式可以$.extend({name:function(){}}) 相似的。作用是干嘛?很简单假设团队有多个人,你担心推展到全局对象中会产生冲突,那么就自己独立建一个属于自己的空间,这样妈妈就在也不用担心儿子程序和别人冲突了!来个例子(如何来读取拓展的属性):

 1 <script type="text/javascript"> 2   $(function() { 3     $.extend({ 4       yyh: { 5         age: 26, 6         address: "chitu", 7         supportCSS3: function() { 8           var body, i, style, transition, vendor; 9           body = document.body || document.documentElement;10           style = body.style;11           transition = "transition";12           vendor = ["Moz", "Webkit", "Khtml", "O", "ms"];13           transition = transition.charAt(0).toUpperCase() + transition.substr(1);14           i = 0;15           while (i < vendor.length) {16             if (typeof style[vendor[i] + transition] === "string") {17               return vendor[i];18             }19             i++;20           }21           return false;22         }23 24       }25     });26     //读取对应的属性27     if($.yyh.supportCSS3){28       alert("浏览器支持css3");29     }30     console.log($.yyh.age);31     console.log($.yyh.address);32   })33   </script>

 

  $.extend(boolean,dest,src1,src2,src3...)

  这中方式,通过boolean,来决定是否深度拷贝!这种方式想必你在很多场合也见过了,boolean默认的是false,可以省略!至于为什么这样做呢?来个例子就豁然开朗了!

 1 <script type="text/javascript"> 2   $(function() { 3     var obj = { 4         name:{ 5           nickname:"丑男孩",//外号 6           truename:"yyh",//真是姓名 7         }, 8         age: 26 9       },10       obj1 = {11         name:{12           nickname:"小男孩",//外号13           truename:"yyh1",//真是姓名14         },15         age:2516       },17       obj2 = {18         name:{19           nickname:"老男孩",//外号20           username:"uglyboy"21         },22         age: 2723       }24     var mergeObj1 = $.extend(true,obj,obj1,obj2);25     //mergeObj1={name:{nickname: "老男孩",truename: "yyh1",username: "uglyboy",age: 27}}26     var mergeObj2 = $.extend(false,obj,obj1,obj2);27     //mergeObj2={name:{nickname: "老男孩",username: "uglyboy",age: 27}}28   })29   </script>

  

  看完上面的例子的时候,你就知道如果false的时候,后面添加的对象的obj2中没有属性truename,合并后对象就不会有truename这个属性,所以写插件的时候会在里面看到如下:

 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4   <meta charset="UTF-8"> 5   <title>demo1</title> 6   <script src="http://libs.baidu.com/jquery/1.10.0/jquery.js"></script> 7 </head> 8  9 <body>10   <script type="text/javascript">11   ;(function($){12     $.fn.Plugin=function(options){13       //如果defaults是下面的形式,这里大可以不加boolean14       var defaults={15         property1:"value1",16         property2:"value2",17         property3:"value3",18         method1:function(){},19         method2:function(){},20       };21       var opt=$.extend(defaults,options);22     }23   })(jQuery)24 25   ;(function($){26     $.fn.Plugin=function(options){27       //如果defaults是下面的形式,亲,记得加上boolean,不然传递参数可麻烦了!28       var defaults={29         property1:{30           property11:"value11",31           property12:"value12",32         },33         property2:{34           property21:"value21",35           property22:"value22",36         },37         property3:{38           property31:"value31",39           property32:"value32",40         },41         method1:function(){},42         method2:function(){},43       };44       45       var opt=$.extend(true,defaults,options);46     }47   })(jQuery)48 49   </script>50 </body>51 52 </html>

 

  二、jquery插件的几种形式

  1、传统的插件写法,defaut没有暴露出来供外部调用(这个应该我们写插件很常用的一种方式),下面是单个实例的时候

 

<!doctype html><html><head>  <meta charset="utf-8">  <title>无标题文档</title>  <script src="http://libs.baidu.com/jquery/1.10.1/jquery.js"></script>  <link rel="stylesheet" type="text/css" href="../css/reset.css">  <style type="text/css">  .undis {    display: none;  }    .tab-parent {    width: 400px;    margin: 50px auto;    border: 1px solid #e5e5e5;  }    .tab-hd {    height: 45px;  }    .tab-hd li {    padding: 15px 0;    width: 200px;    text-align: center;    float: left;    border-bottom: 1px solid #e5e5e5;  }    .tab-hd li.oncurr {    border-color: #f60;    color: #f60;    font-weight: bold;  }    .tab-bd {    padding: 20px;    min-height: 250px;  }  </style></head><body>  <div class="tab-parent" id="J_tab-parent">    <ul class="tab-hd">      <li class="tab-hd-item oncurr">选项卡1</li>      <li class="tab-hd-item">选项卡2</li>    </ul>    <div class="tab-bd">      <div class="tab-bd-item">选项卡1对应的内容</div>      <div class="tab-bd-item undis">选项卡2对应的内容</div>    </div>  </div>  <script type="text/javascript">  (function($) {    $.fn.Tab = function(options) {      var defaults = {        hdClass: '.tab-hd-item',        bdClass: '.tab-bd-item'      };      var opts = $.extend(defaults, options),        $hdItems=this.find(opts.hdClass),        $bdItems=this.find(opts.bdClass);      $hdItems.each(function(index, el) {        var $this=$(this);        $this.on("click",function(){          $this.addClass('oncurr').siblings().removeClass('oncurr');          $bdItems.eq(index).show().siblings().hide();        })      }); 
      //如果想要支持链式写法,在这里请添加return this;  } })(jQuery); $(function() { $("#J_tab-parent").Tab(); }) </script></body></html>

 

  多个实例的时候

<!doctype html><html><head>  <meta charset="utf-8">  <title>无标题文档</title>  <script src="http://libs.baidu.com/jquery/1.10.1/jquery.js"></script>  <link rel="stylesheet" type="text/css" href="../css/reset.css">  <style type="text/css">  .undis {    display: none;  }    .tab-parent {    width: 400px;    margin: 50px auto;    border: 1px solid #e5e5e5;  }    .tab-hd {    height: 45px;  }    .tab-hd li {    padding: 15px 0;    width: 200px;    text-align: center;    float: left;    border-bottom: 1px solid #e5e5e5;  }    .tab-hd li.oncurr {    border-color: #f60;    color: #f60;    font-weight: bold;  }    .tab-bd {    padding: 20px;    min-height: 250px;  }  </style></head><body>  <div class="tab-parent" id="J_tab-parent">    <ul class="tab-hd">      <li class="tab-hd-item oncurr">选项卡1</li>      <li class="tab-hd-item">选项卡2</li>    </ul>    <div class="tab-bd">      <div class="tab-bd-item">选项卡1对应的内容</div>      <div class="tab-bd-item undis">选项卡2对应的内容</div>    </div>  </div>  <div class="tab-parent" id="J_tab-parent">    <ul class="tab-hd">      <li class="tab-hd-item oncurr">选项卡1</li>      <li class="tab-hd-item">选项卡2</li>    </ul>    <div class="tab-bd">      <div class="tab-bd-item">选项卡1对应的内容</div>      <div class="tab-bd-item undis">选项卡2对应的内容</div>    </div>  </div>  <script type="text/javascript">  (function($) {    $.fn.Tab = function(options) {      var defaults = {        hdClass: '.tab-hd-item',        bdClass: '.tab-bd-item'      };      var opts = $.extend(defaults, options);      return this.each(function(index, el) {        var $hdItems=$(this).find(opts.hdClass),          $bdItems=$(this).find(opts.bdClass);          $hdItems.each(function(index, el) {            var $this=$(this);            $this.on("click",function(){              $this.addClass('oncurr').siblings().removeClass('oncurr');              $bdItems.eq(index).show().siblings().hide();            })          });       });                  }  })(jQuery);  $(function() {    $(".tab-parent").Tab();  })  </script></body></html>

  

  2、default写成$.fn.default暴露出来供外部调用(这种方式的插件写法是很经常遇到的,比如jquery.cycle2.js),这个时候你应该会联想到$.fn.format在插件中的用法,这样的好处是可以让用户自定义自己的操作行为,而不用每次实例的时候都去传递同样的阐述,如下的例子:

 

<!doctype html><html><head>  <meta charset="utf-8">  <title>无标题文档</title>  <script src="http://libs.baidu.com/jquery/1.10.1/jquery.js"></script>  <link rel="stylesheet" type="text/css" href="../css/reset.css">  <style type="text/css">  .undis {    display: none;  }    .tab-parent {    width: 400px;    margin: 50px auto;    border: 1px solid #e5e5e5;  }    .tab-hd {    height: 45px;  }    .tab-hd li {    padding: 15px 0;    width: 200px;    text-align: center;    float: left;    border-bottom: 1px solid #e5e5e5;  }    .tab-hd li.oncurr {    border-color: #f60;    color: #f60;    font-weight: bold;  }    .tab-bd {    padding: 20px;    min-height: 250px;  }  </style></head><body>  <div class="tab-parent" id="J_tab-parent">    <ul class="tab-hd">      <li class="tab-hd-item-1 oncurr">选项卡1</li>      <li class="tab-hd-item-1">选项卡2</li>    </ul>    <div class="tab-bd">      <div class="tab-bd-item-1">选项卡1对应的内容</div>      <div class="tab-bd-item-1 undis">选项卡2对应的内容</div>    </div>  </div>  <script type="text/javascript">  (function($) {    $.fn.Tab = function(options) {      var opts = $.extend($.fn.Tab.defaults, options);      return this.each(function(index, el) {        var $hdItems = $(this).find(opts.hdClass),          $bdItems = $(this).find(opts.bdClass);        $hdItems.each(function(index, el) {          var $this = $(this);          $this.on("click", function() {            $(this).html($.fn.Tab.format($(this).text()));            $this.addClass('oncurr').siblings().removeClass('oncurr');            $bdItems.eq(index).show().siblings().hide();          })        });      });    }    $.fn.Tab.defaults = {      hdClass: '.tab-hd-item',      bdClass: '.tab-bd-item'    };    $.fn.Tab.format = function(txt) {      return '<strong>' + txt + '</strong>';    };  })(jQuery);  $(function() {    $.fn.Tab.defaults = {      hdClass: '.tab-hd-item-1',      bdClass: '.tab-bd-item-1'    };    $(".tab-parent").Tab();  })  </script></body></html>

 

  3、通过data的方式来实现jquery插件的写法(参考bootstrap.js,slidesjs)  

<!doctype html><html><head>  <meta charset="utf-8">  <title>无标题文档</title>  <script src="http://libs.baidu.com/jquery/1.10.1/jquery.js"></script>  <link rel="stylesheet" type="text/css" href="../css/reset.css">  <style type="text/css">  .undis {    display: none;  }    .tab-parent {    width: 400px;    margin: 50px auto;    border: 1px solid #e5e5e5;  }    .tab-hd {    height: 45px;  }    .tab-hd li {    padding: 15px 0;    width: 200px;    text-align: center;    float: left;    border-bottom: 1px solid #e5e5e5;  }    .tab-hd li.oncurr {    border-color: #f60;    color: #f60;    font-weight: bold;  }    .tab-bd {    padding: 20px;    min-height: 250px;  }  </style></head><body>  <div class="tab-parent" id="J_tab-parent">    <ul class="tab-hd">      <li class="tab-hd-item oncurr">选项卡1</li>      <li class="tab-hd-item">选项卡2</li>    </ul>    <div class="tab-bd">      <div class="tab-bd-item">选项卡1对应的内容</div>      <div class="tab-bd-item undis">选项卡2对应的内容</div>    </div>  </div>  <script type="text/javascript">  ;(function($, window, document, undefined) {    var pluginName = 'Tab',      defaults = {        hdClass: '.tab-hd-item',        bdClass: '.tab-bd-item'      };    function Plugin(element, options) {      this.element = element;      this.options = $.extend({}, defaults, options);      this._defaults = defaults;      this._name = pluginName;      this.init();    }    Plugin.prototype.init = function() {      this.$hdItems = $(this.element).find(".tab-hd-item");      this.$bdItems = $(this.element).find(this.options.bdClass);      var _this = this;      this.$hdItems.each(function(index, el) {        var $this = $(this);        $this.on("click", function() {          $this.addClass('oncurr').siblings().removeClass('oncurr');          _this.$bdItems.eq(index).show().siblings().hide();        })      });    }    $.fn[pluginName] = function(options) {      return this.each(function() {        if (!$.data(this, 'plugin_' + pluginName)) {          return $.data(this, 'plugin_' + pluginName, new Plugin(this, options));        }      })    }  })(jQuery, window, document);  $(function() {    $("#J_tab-parent").Tab()  })  </script></body></html>

   基本的插件形式就这这三种,当然我们依然可以找到其他的方式的插件,比如私有方法的放置,还有像bootstrap.js的框架的细微的变形,万变不离其中,只要了解基本的方法,其他的都可以依葫芦画瓢!