km之路--008 jquery 001 插件開發 規範

命名規範

一般狀況下采用下面的模式進行命名:javascript

jquery.pluginName.js

min版則採用與之相似的命名規劃,並添加一個min標記:css

jquery.pluginName.min.js

擴展jquery的三種方法

1. 經過一個簡單的、jquery函數prototype屬性的別名(jquery.fn)進行擴展html

這種方法其是實添加一個函數,例如each、ajax這樣的
2. 使用jquery.extend()方法前端

這是日常使用的方式
3. 使用jquery ui widget factory進行擴展java

這是jquery ui中的,不過它能夠脫離jquery ui運行。這種方法能夠建立有狀態的插件。jquery

 

以前寫的摺疊面板

css

 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 }

 

js

 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插件開發最佳實踐

總的來講jquery插件開發有以下最佳實踐:

1. 在jquery名稱空間中只爲插件聲明單個名稱
2. 爲插件中的事件和數據定義名稱空間
3. 接收一個options參數以控制插件的行爲
4. 爲插件的默認設置提供公開的訪問
5. 保護私有函數的私有性
6. 公開須要公開的函數
7. 支持鏈式調用

這裏就不考慮metadata插件了,由於$.data已經提供了相似的功能

固然,如今只是開發摺疊面板、下拉菜單、tab選項面板之類的簡單插件,若是要開發datagrid等插件,我認爲須要使用jquery ui widget factory。

 

一個自定義事件的例子

這個例子實現的功能很簡單,

在一個div中有一個按鈕

div默認有邊框和padding

單擊按鈕能夠改變邊框顏色或者去掉padding

當邊框改變以後,觸發自定義事件【重難點】

js

  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項目插件體系規劃

 

N-2

研究 jquery ui 源碼

N-1

研究Bootstrap js組件源碼

 

終極目標

基於es5/6構建KM項目前端JS UI庫

相關文章
相關標籤/搜索