• km之路--008 jquery 001 插件开发 规范


    命名规范

    通常情况下采用下面的模式进行命名:

    jquery.pluginName.js

    min版则采用与之类似的命名规划,并添加一个min标记:

    jquery.pluginName.min.js

    扩展jquery的三种方法

    1. 通过一个简单的、jquery函数prototype属性的别名(jquery.fn)进行扩展

    这种方法其是实添加一个函数,例如each、ajax这样的
    2. 使用jquery.extend()方法

    这是平常使用的方式
    3. 使用jquery ui widget factory进行扩展

    这是jquery ui中的,不过它可以脱离jquery ui运行。这种方法可以创建有状态的插件。

    之前写的折叠面板

    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. 面板插件绑定了面板内容的展示,无法自定义

    2. 样式比较难看【好吧,以我目前的CSS水平来说,能写/抄出这样的效果已经很不错了】

    3. 没有图标

    4. 无法加载远程数据【这是最无法接受的

    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库

    khl
  • 相关阅读:
    一文快速入门分库分表(必修课)
    MySql分库分表与分区的区别和思考
    常用分库分表方案汇总
    分区分表分库
    MySQL分区和分表
    MySQL的聚集索引和非聚集索引
    PHP大文件上传支持断点上传组件
    PHP大文件上传支持断点上传工具
    Nginx大文件上传支持断点上传
    百度WebUploader大文件上传支持断点上传
  • 原文地址:https://www.cnblogs.com/khlbat/p/8176986.html
Copyright © 2020-2023  润新知