• 用类与原型写一个组件(二)——学习笔记


      上一篇里,我们为smartList组件写了一个简单的setData方法,运用此原型方法创建了member list和group list两个列表,今天我们继续完善插件功能。

      上一篇里,最终效果是这样:

      生成了2个一模一样的列表,都有编辑和删除的功能。所以现在我们要改进一下插件,使用户可以定制出不一样的列表(选择性的拥有编辑和删除功能)。

      我们想在创建对象的时候就能定制。像下面这样:

    1   // 定义一个SmartList类
    2   function SmartList(selector, isDeletable) {
    3     this.list = [];
    4     this.isDeletable = isDeletable;
    5     this.element = $(selector)
    6       .addClass('panel-group xx-smartlist');
    7     console.log('----创建了一个SmartList对象----');
    8   }
    1   $(function () {
    2     // 初始化一个SmartList的实例对象
    3     var memberList = new xx.SmartList('#memberList',false);
    4     var groupList = new xx.SmartList('#groupList',true);
    5     // 调用原型方法更新数据
    6     memberList.setData(members);
    7     groupList.setData(groups);
    8 
    9   });

      由于我们是个字符串,所以可以判断一下,不能删除时就返回一个空字符串。

    1 this.isDeletable ? '<i data-act="del" class="glyphicon glyphicon-remove pull-right"></i>' : '',

      到这里就处理完毕了,看一下效果:

      同理可定制编辑,再加一个参数就行。完整代码如下:

    smartList.js

     1 /**
     2  * SmartList
     3  *
     4  * 数据源:id为必须项
     5  */
     6 
     7 + function (Flexx) {
     8   'use strict';
     9 
    10   // 定义一个SmartList类
    11   function SmartList(selector, isDeletable,isEditable) {
    12     this.list = [];
    13     this.isDeletable = isDeletable;
    14     this.isEditable = isEditable;
    15     this.element = $(selector)
    16       .addClass('panel-group xx-smartlist');
    17     console.log('----创建了一个SmartList对象----');
    18   }
    19 
    20   // 更新列表
    21   SmartList.prototype.setData = function (list) {
    22     var self = this;
    23     // 更新list数据
    24     this.list = list;
    25     // 清空dom容器
    26     this.element.html('');
    27     // 渲染元素
    28     $.each(this.list, function (i, data) {
    29       self._genItem(data).appendTo(self.element);
    30 
    31     });
    32 
    33     console.log('-> setData done', this.element);
    34   };
    35 
    36 
    37   // 生成一个条目
    38   SmartList.prototype._genItem = function (data) {
    39     var heading = 'heading_' + data.id;
    40     var collapse = 'collapse_' + data.id;
    41     var html = [
    42       '<div class="panel panel-default" data-id="' + data.id + '">',
    43       '<div class="panel-heading" role="tab" id="' + heading + '">',
    44       '<h4 class="panel-title">',
    45       '<a role="button" data-toggle="collapse" data-parent="#memberList" href="#' +
    46       collapse + '" aria-expanded="true" aria-controls="' + collapse + '">',
    47       data.title,
    48       '</a>',
    49       this.isDeletable ? '<i data-act="del" class="glyphicon glyphicon-remove pull-right"></i>' : '',
    50       this.isEditable?'<i data-act="edit" class="glyphicon glyphicon-pencil pull-right"></i>':'',
    51       '</h4>',
    52       '</div>',
    53       '<div id="' + collapse + '" class="panel-collapse collapse" role="tabpanel" aria-labelledby="' + heading + '">',
    54       '<div class="panel-body">',
    55       data.content,
    56       '</div>',
    57       '</div>',
    58       '</div>'
    59     ].join('');
    60 
    61     return $(html);
    62   };
    63 
    64   Flexx.SmartList = SmartList;
    65 
    66 }(window.xx = window.xx || {});
    View Code

    在main.js中调用:

     1 + function () {
     2   'use strict';
     3 
     4   // 创建一个用来测试的模拟数据
     5   var members = [{
     6     id: 0,
     7     title: 'Brandon',
     8     content: 'hello'
     9   }, {
    10     id: 1,
    11     title: 'Kim',
    12     content: 'hi'
    13   }, {
    14     id: 2,
    15     title: 'Bunny',
    16     content: 'hi'
    17   }, {
    18     id: 3,
    19     title: 'Lovelyun',
    20     content: 'hi'
    21   }];
    22 
    23   var groups = [{
    24     id: 1,
    25     title: 'Web Dev',
    26     content: 'hello again'
    27   }];
    28 
    29   $(function () {
    30     // 初始化一个SmartList的实例对象
    31     var memberList = new xx.SmartList('#memberList',false,true);
    32     var groupList = new xx.SmartList('#groupList',true,false);
    33     // 调用原型方法更新数据
    34     memberList.setData(members);
    35     groupList.setData(groups);
    36 
    37   });
    38 
    39 }();
    View Code

    效果图如下:

      但是大家有没有注意到,为了这2个功能的定制,使得创建对象的参数变多了,而且参数还要一一对应,如果前面某个参数不传,还得写个null。

      如果参数再多一点呢?谁用谁知道!所以我们把重要的参数selector留着,其他定制的参数全放在一个options中。

    1   // 定义一个SmartList类
    2   function SmartList(selector, options) {
    3     this.list = [];
    4     this.options = options;
    5     this.element = $(selector)
    6       .addClass('panel-group xx-smartlist');
    7     console.log('----创建了一个SmartList对象----');
    8   }
    1 this.options.isDeletable ? '<i data-act="del" class="glyphicon glyphicon-remove pull-right"></i>' : '',
    2 this.options.isEditable?'<i data-act="edit" class="glyphicon glyphicon-pencil pull-right"></i>':'',

      改动以上2处代码后这样调用:

     1   $(function () {
     2     // 初始化一个SmartList的实例对象
     3     var memberList = new xx.SmartList('#memberList',{
     4       isDeletable:false,
     5       isEditable:true
     6     });
     7     var groupList = new xx.SmartList('#groupList',{
     8       isDeletable:true,
     9       isEditable:false
    10     });
    11     // 调用原型方法更新数据
    12     memberList.setData(members);
    13     groupList.setData(groups);
    14 
    15   });

      可以达到同样的效果。但是这样有一个问题,不知道大家发现没有:如果传入参数,就能定制,但不传参数就报错了。

      那么,不传第二个参数的时候 options 是什么?当然是undefined啦!所以,为了解决这个问题,我们可以给这2个参数设一个默认值,在使用的时候,如果没有参数传进来,就使用默认值。

      怎么设置这个默认值呢?方法有很多,我们从易到难一一道来(代码截图注意看行号,就知道改动了哪里)。

      一:判断options里面有没有对应属性:

      二:判断对应的属性是否被赋值:

      三:判断对应的属性值是否是布尔值(判断更精确):

      但以上方法代码还是太多了,下面用三目来判断:

      上面的两个感叹号,用来将某个值转化为bool,因为isDeletable和isEditable有可能未定义,一个!是取反,只要有值就是false,再来一个,只要有值就是true了。

       到这里,得到最佳解决方案了吗?

      NO,我们虽然给options设置了默认值,但是,如果属性再继续增加呢?所以我们要把属性追加到options,而不是赋值给options。故最终解决办法如下:

      如果没有传options,也不会未定义,如果传入了,则覆盖默认属性。这还有一个好处就是让属性名显示出来,让用户知道有哪些属性可以设置。

      现在可以控制相关功能的按钮是否在页面显示了,下一步就是写一个remove事件并绑定。

     1   SmartList.prototype.remove = function(id){
     2     var self = this;
     3 
     4     $.each(this.list, function (i, val) {
     5       if (val.id === id) {
     6         self.list.splice(i, 1);
     7         self.element.find('[data-id="' + id + '"]').remove();
     8         return false;
     9       }
    10     });
    11   }
     1   // 生成一个条目
     2   SmartList.prototype._genItem = function (data) {
     3     var self = this;
     4     var heading = 'heading_' + data.id;
     5     var collapse = 'collapse_' + data.id;
     6     var html = [
     7       '<div class="panel panel-default" data-id="' + data.id + '">',
     8       '<div class="panel-heading" role="tab" id="' + heading + '">',
     9       '<h4 class="panel-title">',
    10       '<a role="button" data-toggle="collapse" data-parent="#memberList" href="#' +
    11       collapse + '" aria-expanded="true" aria-controls="' + collapse + '">',
    12       data.title,
    13       '</a>',
    14       this.options.isDeletable ? '<i data-act="del" class="glyphicon glyphicon-remove pull-right"></i>' : '',
    15       this.options.isEditable?'<i data-act="edit" class="glyphicon glyphicon-pencil pull-right"></i>':'',
    16       '</h4>',
    17       '</div>',
    18       '<div id="' + collapse + '" class="panel-collapse collapse" role="tabpanel" aria-labelledby="' + heading + '">',
    19       '<div class="panel-body">',
    20       data.content,
    21       '</div>',
    22       '</div>',
    23       '</div>'
    24     ].join('');
    25     var item = $(html);
    26 
    27     if(this.options.isDeletable){
    28       item.find('[data-act="del"]').click(function(){
    29         self.remove(data.id);
    30       });
    31     }
    32       
    33     return item;
    34   };

      现在,我们可以让用户定制列表是否拥有编辑或删除功能了。完整代码如下。

    index.html:

     1 <html>
     2 <head>
     3   <meta charset="UTF-8">
     4   <title>Flexx</title>
     5   <link href="http://apps.bdimg.com/libs/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet">
     6   <link rel="stylesheet" href="./css/main.css">
     7   <script src="http://apps.bdimg.com/libs/jquery/2.0.0/jquery.min.js"></script>
     8   <script src="http://apps.bdimg.com/libs/bootstrap/3.3.0/js/bootstrap.min.js"></script>
     9   <script src="./js/flexx.js"></script>
    10   <script src="./js/smartList.js"></script>
    11   <script src="./js/main.js"></script>
    12 </head>
    13 <body>
    14   <div class="container">
    15     <h1>Flexx Library</h1>
    16     <hr>
    17     <div class="row">
    18       <div class="col-xs-6">
    19         <div id="memberList"></div>
    20       </div>
    21       <div class="col-xs-6">
    22         <div id="groupList"></div>
    23       </div>
    24     </div>
    25   </div>
    26 </body>
    27 </html>
    View Code

    smartList.js:

     1 /**
     2  * SmartList
     3  *
     4  * 数据源:id为必须项
     5  */
     6 
     7 + function (Flexx) {
     8   'use strict';
     9 
    10   // 定义一个SmartList类
    11   function SmartList(selector, options) {
    12     this.list = [];
    13     //覆盖默认属性
    14     this.options = $.extend({
    15       //默认属性
    16       isDeletable: true,// 设置是否有行删除按钮
    17       isEditable: true// 设置是否有行编辑按钮
    18     }, options);
    19    
    20     this.element = $(selector)
    21       .addClass('panel-group xx-smartlist');
    22     console.log('----创建了一个SmartList对象----');
    23   }
    24 
    25   // 更新列表
    26   SmartList.prototype.setData = function (list) {
    27     var self = this;
    28     // 更新list数据
    29     this.list = list;
    30     // 清空dom容器
    31     this.element.html('');
    32     // 渲染元素
    33     $.each(this.list, function (i, data) {
    34       self._genItem(data).appendTo(self.element);
    35 
    36     });
    37 
    38     console.log('-> setData done', this.element);
    39   };
    40 
    41   SmartList.prototype.remove = function(id){
    42     var self = this;
    43 
    44     $.each(this.list, function (i, val) {
    45       if (val.id === id) {
    46         self.list.splice(i, 1);
    47         self.element.find('[data-id="' + id + '"]').remove();
    48         return false;
    49       }
    50     });
    51   }
    52 
    53   // 生成一个条目
    54   SmartList.prototype._genItem = function (data) {
    55     var self = this;
    56     var heading = 'heading_' + data.id;
    57     var collapse = 'collapse_' + data.id;
    58     var html = [
    59       '<div class="panel panel-default" data-id="' + data.id + '">',
    60       '<div class="panel-heading" role="tab" id="' + heading + '">',
    61       '<h4 class="panel-title">',
    62       '<a role="button" data-toggle="collapse" data-parent="#memberList" href="#' +
    63       collapse + '" aria-expanded="true" aria-controls="' + collapse + '">',
    64       data.title,
    65       '</a>',
    66       this.options.isDeletable ? '<i data-act="del" class="glyphicon glyphicon-remove pull-right"></i>' : '',
    67       this.options.isEditable?'<i data-act="edit" class="glyphicon glyphicon-pencil pull-right"></i>':'',
    68       '</h4>',
    69       '</div>',
    70       '<div id="' + collapse + '" class="panel-collapse collapse" role="tabpanel" aria-labelledby="' + heading + '">',
    71       '<div class="panel-body">',
    72       data.content,
    73       '</div>',
    74       '</div>',
    75       '</div>'
    76     ].join('');
    77     var item = $(html);
    78 
    79     if(this.options.isDeletable){
    80       item.find('[data-act="del"]').click(function(){
    81         self.remove(data.id);
    82       });
    83     }
    84       
    85     return item;
    86   };
    87 
    88   Flexx.SmartList = SmartList;
    89 
    90 }(window.xx = window.xx || {});
    View Code

    main.js:

     1 + function () {
     2   'use strict';
     3 
     4   // 创建一个用来测试的模拟数据
     5   var members = [{
     6     id: 0,
     7     title: 'Brandon',
     8     content: 'hello'
     9   }, {
    10     id: 1,
    11     title: 'Kim',
    12     content: 'hi'
    13   }, {
    14     id: 2,
    15     title: 'Bunny',
    16     content: 'hi'
    17   }, {
    18     id: 3,
    19     title: 'Lovelyun',
    20     content: 'hi'
    21   }];
    22 
    23   var groups = [{
    24     id: 1,
    25     title: 'Web Dev',
    26     content: 'hello again'
    27   }];
    28 
    29   $(function () {
    30     // 初始化一个SmartList的实例对象
    31     var memberList = new xx.SmartList('#memberList',{
    32       isDeletable:false,
    33       isEditable:true
    34     });
    35     var groupList = new xx.SmartList('#groupList');
    36     // 调用原型方法更新数据
    37     memberList.setData(members);
    38     groupList.setData(groups);
    39 
    40   });
    41 
    42 }();
    43 aaa
    View Code

      现在做个总结:

    1、注意性能优化。

      最后一步绑定事件为什么还需要判断?为false的时候根本不会显示在页面呀!但是,不显示,还去选择干什么?记住:性能优化就是从代码的点点滴滴累积出来的。

    2、两个js潜规则。

      一般只要是bool值我们都用is开头(比如smartList.js中的isDeletable和isEditable);

      数组我们习惯用复数(比如main.js中的members),但如果你叫xxxList 就不用了。

    潜规则能让你快速读懂别人的代码,反之亦然,这些都是一些良好习惯,从字面上让人理解作者意图。

    最后,感谢大神CX的讲解。

  • 相关阅读:
    JSP application用法
    JSP到底内置了几大对象?
    ConcurrentHashMap之实现细节 5
    假如我是JAVA开发人员
    jBPM
    ServletContext与ServletConfig分析
    oracle建立索引原则
    70个新鲜实用的JavaScript和Ajax技术(上)
    ConcurrentHashMap之实现细节
    ConcurrentHashMap之实现细节3
  • 原文地址:https://www.cnblogs.com/lovelyun/p/5091319.html
Copyright © 2020-2023  润新知