首页 新闻 会员 周边 捐助

一个小demo,想封装成一个可复用的类似插件,或者是推翻重写,其实就是想看看高质量代码

0
悬赏园豆:20 [已解决问题] 解决于 2017-04-19 22:07
  1 <!DOCTYPE html>
  2 <html>
  3 
  4 <head>
  5     <meta charset="UTF-8">
  6     <title>多选框问题</title>
  7 </head>
  8 
  9 <body>
 10     <!--<input type="text" data-bind-content="name" />
 11         <span data-bind-content='name'></span>-->
 12 
 13     <h4>选择区</h4>
 14     <div>
 15         
 16         <ul id="ul1">
 17             <li>全选<input type="checkbox" name="checkall" /></li>
 18             <li><input type="checkbox" name="checkthis" /><span>1</span></li>
 19             <li><input type="checkbox" name="checkthis" /><span>2</span></li>
 20             <li><input type="checkbox" name="checkthis" /><span>3</span></li>
 21             <li><input type="checkbox" name="checkthis" /><span>4</span></li>
 22             <li><input type="checkbox" name="checkthis" /><span>5</span></li>
 23         </ul>
 24     </div>
 25     
 26     <button id="add">添加</button>
 27     <h4>展示区</h4>
 28     <ul id="ul2"></ul>
 29 </body>
 30 <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
 31 <script type="text/javascript">
 32     //封装
 33     var checkBox = (function () {
 34         var globalV = [];
 35         var yourChose = function (tableId, addClickId, showId) {
 36             console.log($('#' + tableId + ' input[name=checkall]'));
 37             //全选
 38             $('#' + tableId + ' input[name=checkall]').click(function () {
 39                 //如果选择全选, 所有的选择框都选中,去除全选,所有的选择框去除选中    
 40                 if ($(this).prop('checked')) {
 41                     $('#' + tableId + ' input[name=checkthis]').prop('checked', true);
 42                     //全选的时候,将所有选框的数据取出来传给全局变量globalV
 43                     $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
 44                         var choseDate = {};
 45                         choseDate.isChecked = true;
 46                         choseDate.id = $(ele).parent().children('span').html();
 47                         globalV.push(choseDate);
 48                     });
 49                 } else {
 50                     $('#' + tableId + ' input[name=checkthis]').prop('checked', false);
 51                 }
 52                 console.log(globalV);
 53             })
 54             //对各个选择框绑定事件
 55             $('#' + tableId).on('change', 'input[name=checkthis]', function () {
 56                 var arr = [];//存储每个选择框的状态
 57                 var choseDate = {};//存储被选中的选择框的数据
 58                 //<li><input type="checkbox" name="check-this" /><span>3</span></li>获取span里面的值
 59                 var this_value = $(this).parent().children('span').html();
 60                 //遍历每个选择框取选择的状态
 61                 $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
 62                     arr.push($(ele).prop('checked'));
 63                 });
 64                 //如果有未选中的状态,去除全选框的选中状态,否则保留添加全选框的的选中状态
 65                 if (arr.indexOf(false) == -1) {
 66                     $('#' + tableId + ' input[name=checkall]').prop('checked', true);
 67                 } else {
 68                     $('#' + tableId + ' input[name=checkall]').prop('checked', false);
 69                 }
 70                 //对应每个选择框的change事件,如果这个选择框选中,则存储这个选择框的数据,否则遍历存储数据的变量,移除这个取消选中的的选择框的数据
 71                 if ($(this).is(':checked')) {
 72                     choseDate.isChecked = true;
 73                     choseDate.id = this_value;
 74                     globalV.push(choseDate);
 75                 } else {
 76                     for (var i = 0; i < globalV.length; i++) {
 77                         if (this_value == globalV[i].id) {
 78                             globalV.splice(i, 1);
 79                         }
 80                     }
 81                 }
 82                 console.log(globalV);
 83             });
 84             //点击添加按钮的事件
 85             $('#'+addClickId).click(function (e) {
 86                 e.preventDefault();
 87                 $('#'+showId).empty();//清空展示区里面的内容
 88                 console.log(globalV);
 89                 //如果没有选中任何选择框,则弹出提示
 90                 if (globalV.length == 0) {
 91                     alert('请先选择!');
 92                 } else {
 93                     //如果选中了一些选择框,则全局变量数据不为空,开始遍历全局变量
 94                     for (var j = 0; j < globalV.length; j++) {
 95                         //按照全局变量globalV,给展示区创建元素;(包含了删除按钮)
 96                         var liElement = '<li>\
 97                                             <span>'+ globalV[j].id + '</span>\
 98                                             <p style="display:inline-block;width:20px;height:20px;background-color:red;border-radius:50%;text-align:center">X</p>\
 99                                         </li>';
100                         $('#'+showId).append(liElement);
101                     }
102                     //给删除按钮添加点击事件
103                     $('#'+showId).on('click', 'p', function () {
104                         //var findAndChangeState=$(this).parent('li').children('span').html();
105                         //找到这个删除按钮对应的父级标签li下面的span标签的内容;注意:这个是简化;就放在了标签里面,实际情况可能是个属性,获取的这个值对应一个选择框
106                         //由这个值来查找对应的选择框,从而改变选择框的状态;
107                         //这里是点击了删除按钮,那么与他对应的选择框的选中状态也会被去除
108                         var findAndChangeState = $(this).parent('li').children('span').html();
109                         //遍历选择框找到与删除按钮对应的选择框,将其状态改为未选中,同时将全选的选择框也改为未选中
110                         $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
111                             if ($(this).parent().children('span').html() == findAndChangeState) {
112                                 $(this).parent().children('input').prop('checked', false);
113                                 $('#' + tableId + ' input[name=checkall]').prop('checked', false);
114                             }
115                         });
116                         //改完之后这个删除按钮对应的父级标签
117                         $(this).parent('li').remove();
118                     })
119                 }
120             })
121         };
122         return {
123             globalV:globalV,
124             yourChose:yourChose
125         }
126     })()
127     checkBox.yourChose('ul1', 'add', 'ul2')
128 </script>
129 
130 </html>

下面这个是我最开始的写的,其实也没变多少.....

复制代码
  1 <!DOCTYPE html>
  2 <html>
  3 
  4 <head>
  5     <meta charset="UTF-8">
  6     <title>多选框问题</title>
  7 </head>
  8 
  9 <body>
 10     <!--<input type="text" data-bind-content="name" />
 11         <span data-bind-content='name'></span>-->
 12 
 13     <h4>选择区</h4>
 14     全选<input type="checkbox" name="check-all" />
 15     <ul id="ul1">
 16         <li><input type="checkbox" name="check-this" /><span>1</span></li>
 17         <li><input type="checkbox" name="check-this" /><span>2</span></li>
 18         <li><input type="checkbox" name="check-this" /><span>3</span></li>
 19         <li><input type="checkbox" name="check-this" /><span>4</span></li>
 20         <li><input type="checkbox" name="check-this" /><span>5</span></li>
 21     </ul>
 22     <button class="add">添加</button>
 23     <h4>展示区</h4>
 24     <ul id="ul2"></ul>
 25 </body>
 26 <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
 27 <script type="text/javascript">
 28     //全局变量,存储传递数据
 29     var globalV = [];
 30     //全选事件
 31     $('input[name=check-all]').click(function () {
 32         globalV = [];
 33         //如果选择全选, 所有的选择框都选中,去除全选,所有的选择框去除选中
 34 
 35         if ($(this).prop('checked')) {
 36             $('input[name=check-this]').prop('checked', true);
 37             //全选的时候,将所有选框的数据取出来传给全局变量globalV
 38             $('#ul1 li').each(function (i, ele) {
 39                 var choseDate = {};
 40                 choseDate.isChecked = true;
 41                 choseDate.id = $(ele).children('span').html();
 42                 globalV.push(choseDate);
 43             });
 44         } else {
 45             $('input[name=check-this]').prop('checked', false);
 46         }
 47         console.log(globalV);
 48     })
 49     //对各个选择框绑定事件
 50     $('#ul1').on('change', 'input[name=check-this]', function () {
 51         var arr = [];//存储每个选择框的状态
 52         var choseDate = {};//存储被选中的选择框的数据
 53         //<li><input type="checkbox" name="check-this" /><span>3</span></li>获取span里面的值
 54         var this_value = $(this).parent('li').children('span').html();
 55         //遍历每个选择框取选择的状态
 56         $('input[name=check-this]').each(function (i, ele) {
 57             arr.push($(ele).prop('checked'));
 58         });
 59         //如果有未选中的状态,去除全选框的选中状态,否则保留添加全选框的的选中状态
 60         if (arr.indexOf(false) == -1) {
 61             $('input[name=check-all]').prop('checked', true);
 62         } else {
 63             $('input[name=check-all]').prop('checked', false);
 64         }
 65         //对应每个选择框的change事件,如果这个选择框选中,则存储这个选择框的数据,否则遍历存储数据的变量,移除这个取消选中的的选择框的数据
 66         if ($(this).is(':checked')) {
 67             choseDate.isChecked = true;
 68             choseDate.id = this_value;
 69             globalV.push(choseDate);
 70         } else {
 71             for (var i = 0; i < globalV.length; i++) {
 72                 if (this_value == globalV[i].id) {
 73                     globalV.splice(i, 1);
 74                 }
 75             }
 76         }
 77         console.log(globalV);
 78     })
 79     //点击添加按钮的事件
 80     $('button.add').click(function (e) {
 81         e.preventDefault();
 82         $('#ul2').empty();//清空展示区里面的内容
 83         console.log(globalV);
 84         //如果没有选中任何选择框,则弹出提示
 85         if (globalV.length == 0) {
 86             alert('请先选择!');
 87         } else {
 88             //如果选中了一些选择框,则全局变量数据不为空,开始遍历全局变量
 89             for (var j = 0; j < globalV.length; j++) {
 90                 //按照全局变量globalV,给展示区创建元素;(包含了删除按钮)
 91                 var liElement = '<li>\
 92                                             <span>'+ globalV[j].id + '</span>\
 93                                             <p style="display:inline-block;width:20px;height:20px;background-color:red;border-radius:50%;text-align:center">X</p>\
 94                                         </li>';
 95                 $('#ul2').append(liElement);
 96             }
 97             //给删除按钮添加点击事件
 98             $('#ul2').on('click', 'p', function () {
 99                 //var findAndChangeState=$(this).parent('li').children('span').html();
100                 //找到这个删除按钮对应的父级标签li下面的span标签的内容;注意:这个是简化;就放在了标签里面,实际情况可能是个属性,获取的这个值对应一个选择框
101                 //由这个值来查找对应的选择框,从而改变选择框的状态;
102                 //这里是点击了删除按钮,那么与他对应的选择框的选中状态也会被去除
103                 var findAndChangeState = $(this).parent('li').children('span').html();
104                 //遍历选择框找到与删除按钮对应的选择框,将其状态改为未选中,同时将全选的选择框也改为未选中
105                 $('#ul1 li').each(function (i, ele) {
106                     if ($(this).children('span').html() == findAndChangeState) {
107                         $(this).children('input').prop('checked', false);
108                         $('input[name=check-all]').prop('checked', false);
109                     }
110                 });
111                 //改完之后这个删除按钮对应的父级标签
112                 $(this).parent('li').remove();
113             })
114         }
115     })
116 </script>
117 
118 </html>
复制代码

目的就是想就这个demo看看高质量代码怎么写,好提高自己,还请各位大神多多教导,谢谢

流年之外天空蓝的主页 流年之外天空蓝 | 初学一级 | 园豆:99
提问于:2017-04-13 00:48
< >
分享
最佳答案
0
  1. 首先,你的初版代码我拿来一用,感觉bug不少(双击‘全选’,然后‘添加’.....),本来还知道你想实现什么,点到后面我都不知道你到底要干嘛了...跟我有的一拼了。
  2. 优化代码前先把思路理清了,你代码看得逻辑没什么问题,但数据啊、画面状态啊,这边那边都在改,互相牵扯,不容易拓展,过段时间回来改bug得酝酿半天。
  3. 你的封装思路还是可以的,我暂且在你的大架子上改一版,思路应该明确一些,一个函数该干什么就干什么,函数功能间尽量别重复,你之前代码就有点太“直观”,眼下该干什么就干什么,好点的思路是“记住你该干些什么,然后把该干的事儿分类一起干了”
  4. 这里面有一点mvc的影子,你可以去慢慢理解下mvc的思想,我最经也在学习
<!--
event{
    select:fun1,
    add:fun2,
    remove:fun3,
}

mvc:
model
controller
view
-->
<!DOCTYPE html>
 <html>
 
 <head>
     <meta charset="UTF-8">
     <title>多选框问题</title>
 </head>
 
 <body>
     <!--<input type="text" data-bind-content="name" />
         <span data-bind-content='name'></span>-->
 
     <h4>选择区</h4>
     <div>
         
         <ul id="ul1">
             <li>全选<input type="checkbox" name="checkall" /></li>
             <li><input type="checkbox" name="checkthis" /><span>1</span></li>
             <li><input type="checkbox" name="checkthis" /><span>2</span></li>
             <li><input type="checkbox" name="checkthis" /><span>3</span></li>
             <li><input type="checkbox" name="checkthis" /><span>4</span></li>
             <li><input type="checkbox" name="checkthis" /><span>5</span></li>
         </ul>
     </div>
     
     <button id="add">添加</button>
     <h4>展示区</h4>
     <ul id="ul2"></ul>
 </body>
 <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
 <script type="text/javascript">
     //封装
     var checkBox = (function () {
             
         var globalV = [];
         var yourChose = function (tableId, addClickId, showId) {
            //负责更新数据            
            var updateData = function(){
                globalV = [];
                $('#' + tableId + ' input[name=checkthis]').each(function(){
                    if ($(this).is(':checked')) {
                        var choseDate = {};
                        var this_value = $(this).parent().children('span').html();
                        choseDate.isChecked = true;
                        choseDate.id = this_value;
                        globalV.push(choseDate);
                    }
                });
            }
            
            //负责更新画面
            //checkBox状态
            function fun1(){
                if($(this).attr("name")=="checkthis"){                
                    var arr = [];//存储每个选择框的状态
                    var choseDate = {};//存储被选中的选择框的数据
                    //<li><input type="checkbox" name="check-this" /><span>3</span></li>获取span里面的值
                    var this_value = $(this).parent().children('span').html();
                    //遍历每个选择框取选择的状态
                    $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
                        arr.push($(ele).prop('checked'));
                    });
                    //如果有未选中的状态,去除全选框的选中状态,否则保留添加全选框的的选中状态
                    if (arr.indexOf(false) == -1) {
                        $('#' + tableId + ' input[name=checkall]').prop('checked', true);
                    } else {
                        $('#' + tableId + ' input[name=checkall]').prop('checked', false);
                    }
                }else{
                    //如果选择全选, 所有的选择框都选中,去除全选,所有的选择框去除选中    
                    if ($(this).prop('checked')) {
                        $('#' + tableId + ' input[name=checkthis]').prop('checked', true);
                     } else {
                         $('#' + tableId + ' input[name=checkthis]').prop('checked', false);
                     }
                }
            }    
            //展示区状态(新增)
            function fun2(){
                $('#'+showId).empty();//清空展示区里面的内容
                updateData();
                 //如果没有选中任何选择框,则弹出提示
                 if (globalV.length == 0) {
                     alert('请先选择!');
                 } else {
                     //如果选中了一些选择框,则全局变量数据不为空,开始遍历全局变量
                     for (var j = 0; j < globalV.length; j++) {
                         //按照全局变量globalV,给展示区创建元素;(包含了删除按钮)
                         var liElement = '<li>\
                                             <span>'+ globalV[j].id + '</span>\
                                             <p style="display:inline-block;width:20px;height:20px;background-color:red;border-radius:50%;text-align:center">X</p>\
                                         </li>';
                         $('#'+showId).append(liElement);
                     }
                     //给删除按钮添加点击事件
                     bindEvent('#'+showId +' p',"click",event.removeLi);
                }
            }
            //展示区状态(删除)
            function fun3(){
                         //var findAndChangeState=$(this).parent('li').children('span').html();
                         //找到这个删除按钮对应的父级标签li下面的span标签的内容;注意:这个是简化;就放在了标签里面,实际情况可能是个属性,获取的这个值对应一个选择框
                         //由这个值来查找对应的选择框,从而改变选择框的状态;
                         //这里是点击了删除按钮,那么与他对应的选择框的选中状态也会被去除
                         var findAndChangeState = $(this).parent('li').children('span').html();
                         //遍历选择框找到与删除按钮对应的选择框,将其状态改为未选中,同时将全选的选择框也改为未选中
                         $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
                             if ($(this).parent().children('span').html() == findAndChangeState) {
                                 $(this).parent().children('input').prop('checked', false);
                                 $('#' + tableId + ' input[name=checkall]').prop('checked', false);
                             }
                         });
                         //改完之后这个删除按钮对应的父级标签
                         $(this).parent('li').remove();
            }
            
            //负责注册事件
            var event = {
                    select:fun1,
                    add:fun2,
                    removeLi:fun3
                    };
            var bindEvent = function(selector,type,fun){ 
                    $(selector).bind(type,fun);
                };            
             //对各个选择框绑定事件
             bindEvent('#' + tableId + ' input[type=checkbox]',"click",event.select);
             //点击添加按钮的事件
             bindEvent('#'+addClickId,"click",event.add);
         };
         
         return {
             globalV:globalV,
             yourChose:yourChose
         }
     })()
     checkBox.yourChose('ul1', 'add', 'ul2');
 </script>
 
 </html>
收获园豆:20
codingHeart | 小虾三级 |园豆:1511 | 2017-04-13 11:55

真是非常非常感谢,学到很多,谢谢谢谢

流年之外天空蓝 | 园豆:99 (初学一级) | 2017-04-13 14:05

@流年之外天空蓝: 基本都是你自己的代码,重新组织了下,并不是高质量的,只能勉强算是易理解的。

codingHeart | 园豆:1511 (小虾三级) | 2017-04-13 14:16

@codingHeart: 我按照你的思路把项目的重新写了,算是过关了,,谢谢谢谢

流年之外天空蓝 | 园豆:99 (初学一级) | 2017-04-14 22:05
其他回答(3)
0

 /**
         * 类型判断
         * public method :
         *         tn.type.isArray()
         *         tn.type.isBoolean()
         *         tn.type.isFunction()
         *         tn.type.isNull()
         *         tn.type.isNumber()
         *         tn.type.isObject()
         *         tn.type.isString()
         *         tn.type.isUndefined()
         *         tn.type.isDefined()
         *         tn.type.isNumeric()
         *         tn.type.isDate()
         */
        type: {
          isArray: function() {
                for (var b = 0, c, a = arguments.length; b < a; b++) {
                    c = arguments[b];
                    if (Array.isArray && !Array.isArray(c) || !(module.tn.type.isObject(c) && c.constructor && (c.constructor.toString().indexOf("Array") > -1 || c instanceof Array))) {
                        return false;
                    }
                }
                return true;
            },
            isBoolean: function() {
                for (var b = 0, c, a = arguments.length; b < a; b++) {
                    c = arguments[b];
                    if (!(typeof c === "boolean" || module.tn.type.isObject(c) && c.constructor && (c.constructor.toString().indexOf("Boolean") > -1 || c instanceof Boolean))) {
                        return false;
                    }
                }
                return true;
            },
            isFunction: function() {
                for (var b = 0, a = arguments.length; b < a; b++) {
                    if (typeof arguments[b] !== "function") {
                        return false;
                    }
                }
                return true;
            },
            isNull: function() {
                for (var b = 0, c, a = arguments.length; b < a; b++) {
                    c = arguments[b];
                    if (c === null || module.tn.type.isUndefined(c)) {
                        return true;
                    }
                }
                return false;
            },
            isNumber: function() {
                for (var b = 0, c, a = arguments.length; b < a; b++) {
                    c = arguments[b];
                    if (!(typeof c === "number" || module.tn.type.isObject(c) && c.constructor && (c.constructor.toString().indexOf("Number") > -1 || c instanceof Number)) || isNaN(c)) {
                        return false;
                    }
                }
                return true;
            },
            isObject: function() {
                for (var b = 0, c, a = arguments.length; b < a; b++) {
                    c = arguments[b];
                    if (typeof c !== "object" || c === null) {
                        return false;
                    }
                }
                return true;
            },
            isString: function() {
                for (var b = 0, c, a = arguments.length; b < a; b++) {
                    c = arguments[b];
                    if (!(typeof c === "string" || module.tn.type.isObject(c) && c.constructor && (c.constructor.toString().indexOf("String") > -1 || c instanceof String))) {
                        return false;
                    }
                }
                return true;
            },
            isUndefined: function() {
                for (var b = 0, a = arguments.length; b < a; b++) {
                    if (typeof arguments[b] === "undefined") {
                        return true;
                    }
                }
                return false;
            },
            isDefined: function() {
                for (var a = 0; a < arguments.length; a++) {
                    if (module.tn.type.isUndefined(arguments[a])) {
                        return false;
                    }
                }
                return true;
            },
            isNumeric: function() {
                for (var b = 0, c, a = arguments.length; b < a; b++) {
                    c = arguments[b];
                    if (!(!isNaN(c) && isFinite(c) && (c !== null) && !module.tn.type.isBoolean(c) && !module.tn.type.isArray(c))) {
                        return false;
                    }
                }
                return true;
            },
            isDate: function() {
                for (var b = 0, a = arguments.length; b < a; b++) {
                    o = arguments[b];
                    if (!(module.tn.type.isObject(o) && o.constructor && (o.constructor.toString().indexOf("Date") > -1 || o instanceof Date))) {
                        return false;
                    }
                }
                return true;
            }
        },

[3] | 园豆:1174 (小虾三级) | 2017-04-13 00:57

我是写后端的,谈不上高质量,平时做项目一些工具类,重复调用的插件方法,放在一个js文件里,格式规范,便于阅读维护就差不多了,如果是封装插件,想想那些可变参数做为入参,把执行方法拆分几步,相互调用..

支持(0) 反对(0) [3] | 园豆:1174 (小虾三级) | 2017-04-13 01:01

@[1]: 谢谢,谢谢,麻烦你了,已收藏你提供的代码,

支持(0) 反对(0) 流年之外天空蓝 | 园豆:99 (初学一级) | 2017-04-13 14:01
0

你这个具有业务相关的逻辑,可能并不适合单独封装。

幻天芒 | 园豆:37207 (高人七级) | 2017-04-13 10:59
0

将功能封装起来 

业务 部分公布出去可以编辑 就可以了

小眼睛老鼠 | 园豆:2731 (老鸟四级) | 2017-04-13 18:14
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册