說起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:25 16 }, 17 obj2 = { 18 name:{ 19 nickname:"老男孩",//外號 20 username:"uglyboy" 21 }, 22 age: 27 23 } 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是下面的形式,這里大可以不加boolean 14 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的框架的細微的變形,萬變不離其中,只要了解基本的方法,其他的都可以依葫蘆畫瓢!