一般狀況下采用下面的模式進行命名:javascript
jquery.pluginName.js
min版則採用與之相似的命名規劃,並添加一個min標記:css
jquery.pluginName.min.js
1. 經過一個簡單的、jquery函數prototype屬性的別名(jquery.fn)進行擴展html
這種方法其是實添加一個函數,例如each、ajax這樣的
2. 使用jquery.extend()方法前端
這是日常使用的方式
3. 使用jquery ui widget factory進行擴展java
這是jquery ui中的,不過它能夠脫離jquery ui運行。這種方法能夠建立有狀態的插件。jquery
1 .km-accdion{ 2 width: 100%; 3 overflow: hidden; 4 } 5 6 .km-accdion ul{ 7 margin: 0; 8 padding: 0; 9 } 10 11 .km-accdion ul li{ 12 margin: 0; 13 padding: 0; 14 list-style: none; 15 } 16 17 .km-accdion-menu{ 18 border-top: 1px solid #cccccc; 19 border-bottom: 1px solid #cccccc; 20 } 21 22 .km-accdion-menu a{ 23 display: block; 24 color: #555; 25 text-decoration: none; 26 background-color: #aaaaaa; 27 padding: .5em 1em; 28 } 29 30 .km-accdion-menu a:hover{ 31 color: white; 32 } 33 34 .km-accdion-menu-item{ 35 display: none; 36 } 37 38 .km-accdion-menu-item a{ 39 display: block; 40 color: #555; 41 text-decoration: none; 42 background-color: #dddddd; 43 padding: .5em 1em; 44 border-width: 1px; 45 border-color: transparent; 46 border-top-style: solid; 47 background-clip: padding-box; 48 } 49 50 .km-accdion-menu-item a:hover{ 51 color: #fff; 52 background-color: #cccccc; 53 } 54 55 .km-accdion-menu-item-show{ 56 display: block !important; 57 } 58 59 .km-accdion-menu-item-show a{ 60 display: block; 61 color: #555; 62 text-decoration: none; 63 background-color: #dddddd; 64 padding: .5em 1em; 65 } 66 67 .km-accdion-menu-item-show a:hover{ 68 color: #fff; 69 background-color: #cccccc; 70 }
1 /** 2 * 手風琴插件 3 * TODO 多層嵌套 4 * TODO 前面加小圖標 5 * TODO 去除對 reset.css 的依賴 6 */ 7 ;(function ($) { 8 'use strict'; 9 10 /** 11 * 默認配置 12 * event : 觸發手風琴切換的事件名稱 13 * onlyOneMenuItem : 是否只顯示一個菜單,true 表示只顯示一個,false 表示每一個菜單均可單獨打開與關閉 14 * @type {{event: string, onlyOneMenuItem: boolean}} 15 */ 16 var defaultOption = { 17 event: 'click', 18 onlyOneMenuItem : true 19 }; 20 21 var accdionClass = { 22 accdionItem : '.km-accdion-item', 23 accdionItemStr : 'km-accdion-item', 24 25 accdionMenu : '.km-accdion-menu', 26 accdionMenuStr : 'km-accdion-menu', 27 28 accdionMenuItem : '.km-accdion-menu-item', 29 accdionMenuItemStr : 'km-accdion-menu-item' 30 }; 31 32 /** 33 * 隱藏其它菜單 34 * @param currentItem 當前所在的 $('.km-accdion-item') 對象 35 */ 36 function hideOtherMenuItem( currentItem ){ 37 /** 38 * 39 * 其它菜單隱藏 40 * 思路: 41 * 1. 每次點擊當前item的時候爲其設置一個惟一ID,值爲 currentMenuItemId + 時間戳 + 一個隨機數,如:currentMenuItemId1513119262000578 42 * 2. 經過 $.siblings方法查找當前插件實例中的每一個item,並加上not過濾,過濾值爲當前item的id 43 * 3. 經過slideUp方法隱藏 44 * 45 */ 46 var currentItemId = 'currentMenuItemId' + Date.parse(new Date().toDateString()) + Math.round(Math.random() * 10000); 47 currentItem.attr('id',currentItemId); 48 currentItem.siblings(accdionClass.accdionItem).not('#'+currentItemId).find(accdionClass.accdionMenuItem).slideUp(500); 49 } 50 51 $.fn.kmaccdion = function (options) { 52 53 var option = $.extend({},defaultOption,options); 54 55 return this.each(function () { 56 var self = $(this); 57 58 self.find(accdionClass.accdionItem).each(function () { 59 var currentItem = $(this); 60 currentItem.find(accdionClass.accdionMenu).on(option.event, function () { 61 // 當前菜單的顯示與隱藏 62 var currentMenuItem = $(this); 63 currentMenuItem.next(accdionClass.accdionMenuItem).slideToggle(300); 64 65 if( option.onlyOneMenuItem ){ 66 hideOtherMenuItem(currentItem); 67 } 68 69 }); 70 }); 71 72 }); 73 }; 74 })(jQuery);
1 <!-- category --> 2 <div id="category-container"> 3 <div class="km-accdion"> 4 <div class="km-accdion-item"> 5 <ul class="km-accdion-menu-item-show"> 6 <li><a href="#">所有</a></li> 7 </ul> 8 </div> 9 <div class="km-accdion-item"> 10 <div class="km-accdion-menu"> 11 <a href="#">移動開發</a> 12 </div> 13 <ul class="km-accdion-menu-item"> 14 <li><a href="#">移動開發</a></li> 15 <li><a href="#">Android 開發</a></li> 16 <li><a href="#">ISO 開發</a></li> 17 </ul> 18 </div> 19 <div class="km-accdion-item"> 20 <div class="km-accdion-menu"> 21 <a href="#">前端開發</a> 22 </div> 23 <ul class="km-accdion-menu-item"> 24 <li><a href="#">前端開發</a></li> 25 <li><a href="#">HTML/CSS</a></li> 26 <li><a href="#">JavaScript</a></li> 27 <li><a href="#">HTML5/CSS3</a></li> 28 <li><a href="#">ECMAScript 6</a></li> 29 <li><a href="#">JQuery</a></li> 30 </ul> 31 </div> 32 </div> 33 </div> 34 <!-- // category -->
1. 面板插件綁定了面板內容的展現,沒法自定義ajax
2. 樣式比較難看【好吧,以我目前的CSS水平來講,能寫/抄出這樣的效果已經很不錯了】json
3. 沒有圖標dom
4. 沒法加載遠程數據【這是最沒法接受的】jquery插件
5. 不具有通用性【也是沒法接受的】
6. 面板切換方法太太低級
總的來講jquery插件開發有以下最佳實踐:
1. 在jquery名稱空間中只爲插件聲明單個名稱
2. 爲插件中的事件和數據定義名稱空間
3. 接收一個options參數以控制插件的行爲
4. 爲插件的默認設置提供公開的訪問
5. 保護私有函數的私有性
6. 公開須要公開的函數
7. 支持鏈式調用
這裏就不考慮metadata插件了,由於$.data已經提供了相似的功能
固然,如今只是開發摺疊面板、下拉菜單、tab選項面板之類的簡單插件,若是要開發datagrid等插件,我認爲須要使用jquery ui widget factory。
這個例子實現的功能很簡單,
在一個div中有一個按鈕
div默認有邊框和padding
單擊按鈕能夠改變邊框顏色或者去掉padding
當邊框改變以後,觸發自定義事件【重難點】
1 ;(function ($, window, document, undefined) { 2 3 /** 4 * 插件的私有方法 5 * 初始化 6 * @param jq jquery 對象,和你使用$('#one')得到的對象是同樣的 7 */ 8 function init(jq) { 9 // 初始化步驟: 10 // 1. 初始化插件樣式,這裏就不寫那麼多了 11 console.log('私有方法:init'); 12 13 // 2. 自定義事件 14 // 綁定事件,我這裏是直接綁定在插件自己上面 15 jq.on('onBorderChanged.kmAccordion', jq.config.onBorderChanged); 16 17 // 3. 綁定單擊事件邏輯,實現點擊按鈕,改變padding和border 18 jq.find('button').click(function () { 19 var text = jq.find('button').text(); 20 // 私有方法調用公有方法 21 jq.kmAccordion('changeBorder',text); 22 }); 23 } 24 25 function sayNo() { 26 console.log('私有方法:sayNo'); 27 } 28 29 /** 30 * 插件實現代碼 31 * @param options 若是是json對象,則建立[初始化]插件,若是是字符串,則用來調用插件的公開方法 32 * @param param 當前options是字符串時,表明傳遞給插件公開方法的參數。固然,你能夠不傳 33 * @returns {*} 34 */ 35 $.fn.kmAccordion = function (options, param) { 36 // console.log(this); 37 // 若是是方法調用 38 if (typeof options === 'string') { 39 return $.fn.kmAccordion.methods[options](this, param); 40 } 41 42 // 得到配置,這裏爲了獲得用戶的配置項,覆蓋默認配置項,並保存到當前jquery插件實例中 43 var _opts = $.extend({}, $.fn.kmAccordion.defaults, options); 44 var jq = this; 45 jq.config = _opts; 46 47 // 鏈式調用 48 return this.each(function () { 49 // console.log(this); 50 // 調用私有方法,初始化插件 51 init(jq); 52 }); 53 }; 54 55 56 /** 57 * 插件的公開方法 58 */ 59 $.fn.kmAccordion.methods = { 60 changeBorder: function (jq, text) { 61 // 公有方法能夠相互調用 62 jq.kmAccordion('sayHello'); 63 64 // 公有方法調用私有方法,可是對插件外部來講,私有方法是不可見的 65 sayNo(); 66 67 // 實現邏輯 68 jq.css({'border-color':jq.config.color}); 69 if( jq.config.clearPadding ){ 70 jq.css({'padding':'0'}); 71 } 72 console.log('按鈕文本:'+text); 73 74 // 觸發事件 75 jq.config.onBorderChanged.call(jq, jq.css('border-color')); 76 77 // 返回jquery對象,支持鏈式調用 78 return jq; 79 }, 80 sayHello : function(jq){ 81 console.log('hello'); 82 return jq; 83 }, 84 options: function (jq) { 85 // 這個就不須要支持鏈式調用了 86 return jq.config; 87 } 88 }; 89 90 91 /** 92 * 插件的默認配置 93 */ 94 $.fn.kmAccordion.defaults = { 95 // 屬性 96 clearPadding: true, 97 color: 'blue', 98 99 /** 100 * 自定義事件 101 * @param color 事件觸發時的參數 102 */ 103 onBorderChanged: function (color) { 104 console.log('默認事件實現,固然,你也能夠不實現,留空:' + color); 105 } 106 }; 107 })(jQuery, window, document);
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 div{ 8 border: 1px solid red; 9 padding: 20px; 10 float: left; 11 margin: 20px; 12 } 13 </style> 14 </head> 15 <body> 16 <div id="one"> 17 <button>第一個按鈕</button> 18 </div> 19 <div id="two"> 20 <button>第二個按鈕</button> 21 </div> 22 23 <button id="btnone">調用第一個插件的方法</button> 24 <button id="btntwo">調用第二個插件的方法</button> 25 26 27 28 <script type="text/javascript" charset="UTF-8" src="./external/jquery.min.js"></script> 29 <script type="text/javascript" charset="UTF-8" src="one.js"></script> 30 <script type="text/javascript" charset="UTF-8"> 31 $(function () { 32 // 實例化插件,改變一下默認配置 33 var one = $('#one').kmAccordion({ 34 clearPadding:false, 35 color : 'black', 36 onBorderChanged : function (color) { 37 console.log('自定義事件:'+color); 38 } 39 }); 40 // 實例化插件,使用默認配置 41 var two = $('#two').kmAccordion(); 42 43 $('#btnone').click(function () { 44 console.log('外部調用 公開方法 1'); 45 // 調用插件的方法,同時會觸發自定義事件 46 one.kmAccordion('changeBorder',one.find('button').text()); 47 }); 48 49 $('#btntwo').click(function () { 50 console.log('外部調用 公開方法 2'); 51 // 這個也調用一下 52 two.kmAccordion('changeBorder',two.find('button').text()); 53 }); 54 55 }); 56 </script> 57 </body> 58 </html>
默認運行效果
單擊第一個div中的按鈕
刷新頁面,單擊第二個div中的按鈕
刷新頁面,單擊:《調用第一個插件的方法》按鈕
刷新頁面,單擊:《調用第二個插件的方法》按鈕
能夠看到效果仍是不錯的。
要時刻注意this的指向
把36行和49行註釋打開,刷新頁面,就會看到緣由
上面例子的演變流程
基於MVC的JavaScript Web富應用開發
KM項目插件體系規劃
研究 jquery ui 源碼
研究Bootstrap js組件源碼
基於es5/6構建KM項目前端JS UI庫