用类与原型写一个组件(三)——学习笔记
上一篇中,我们为组件添加了“删除一条item”的功能,现在,再增加一个“增加一条item”的功能。
首先,在页面中增加一个按钮,用来触发添加功能(红框中的内容是对比上一篇新加的代码)。
在main.js中绑定按钮的单击事件,触发add函数。
再在smartList.js里写add函数。
1 // 增加一条数据 2 SmartList.prototype.add = function (data) { 3 4 var isExist = false; 5 6 // 判断id是否已存在 7 $.each(this.list, function (i, val) { 8 if (val.id === data.id) { 9 isExist = true; 10 return false; // 退出循环 11 } 12 }); 13 14 if (isExist) { 15 console.log('SmartList: id ' + data.id + ' 已存在,无法添加'); 16 return; 17 } 18 19 this.list.push(data); 20 this._genItem(data).appendTo(this.element); 21 };
现在可以注意到,$.each(this.list, function (i, val) {...}这行代码重复了,在add里用到了,在remove里也用到了,所以,我们是否可以写一个函数来代替这段重复的代码呢?于是,写一个_getById方法如下:
1 SmartList.prototype._getById = function (id, callback) { 2 var self = this; 3 var data = null; 4 5 $.each(this.list, function (i, val) { 6 if (val.id === id) { 7 data = val; 8 if (callback && typeof callback === 'function') 9 callback(i, data); 10 return false; 11 } 12 }); 13 14 return data; 15 };
现在可以用_getById方法来改写remove和add方法。改写前后对比如下:
完整代码如下:
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 class="row"> 20 <div class="col-xs-12"> 21 <button id="btnAdd" class="btn btn-success"> 22 <i class="glyphicon glyphicon-plus"></i> 23 </button> 24 </div> 25 </div> 26 <br> 27 <div id="memberList"></div> 28 </div> 29 <div class="col-xs-6"> 30 <div id="groupList"></div> 31 </div> 32 </div> 33 </div> 34 </body> 35 </html>
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 13 this.list = []; 14 15 // 覆盖默认属性 16 this.options = $.extend({ 17 // 默认属性 18 isDeletable: true, // 设置是否有行删除按钮 19 isEditable: true // 设置是否有行编辑按钮 20 }, options); 21 22 this.element = $(selector) 23 .addClass('panel-group xx-smartlist'); 24 25 console.log('----创建了一个SmartList对象----'); 26 } 27 28 // 更新列表 29 SmartList.prototype.setData = function (list) { 30 var self = this; 31 // 更新list数据 32 this.list = list; 33 // 清空dom容器 34 this.element.html(''); 35 // 渲染元素 36 $.each(this.list, function (i, data) { 37 self._genItem(data).appendTo(self.element); 38 }); 39 40 console.log('-> setData done', this.element); 41 }; 42 43 // 增加一条数据 44 SmartList.prototype.add = function (data) { 45 if(this._getById(data.id)){ 46 console.log('SmartList: id ' + data.id + ' 已存在,无法添加'); 47 return; 48 } 49 this.list.push(data); 50 this._genItem(data).appendTo(this.element); 51 }; 52 53 SmartList.prototype.remove = function (id) { 54 var self = this; 55 56 this._getById(id, function (i, data) { 57 self.list.splice(i, 1); 58 self.element.find('[data-id="' + id + '"]').remove(); 59 }); 60 }; 61 62 SmartList.prototype._getById = function (id, callback) { 63 var self = this; 64 var data = null; 65 66 $.each(this.list, function (i, val) { 67 if (val.id === id) { 68 data = val; 69 if (callback && typeof callback === 'function') 70 callback(i, data); 71 return false; 72 } 73 }); 74 75 return data; 76 }; 77 78 // 生成一个条目 79 SmartList.prototype._genItem = function (data) { 80 var self = this; 81 var heading = 'heading_' + data.id; 82 var collapse = 'collapse_' + data.id; 83 var html = [ 84 '<div class="panel panel-default" data-id="' + data.id + '">', 85 '<div class="panel-heading" role="tab" id="' + heading + '">', 86 '<h4 class="panel-title">', 87 '<a role="button" data-toggle="collapse" data-parent="#memberList" href="#' + 88 collapse + '" aria-expanded="true" aria-controls="' + collapse + '">', 89 data.title, 90 '</a>', 91 this.options.isDeletable ? '<i data-act="del" class="glyphicon glyphicon-remove pull-right"></i>' : '', 92 this.options.isEditable ? '<i data-act="edit" class="glyphicon glyphicon-pencil pull-right"></i>' : '', 93 '</h4>', 94 '</div>', 95 '<div id="' + collapse + '" class="panel-collapse collapse" role="tabpanel" aria-labelledby="' + heading + '">', 96 '<div class="panel-body">', 97 data.content, 98 '</div>', 99 '</div>', 100 '</div>' 101 ].join(''); 102 103 var item = $(html); 104 105 if (this.options.isDeletable) { 106 item.find('[data-act="del"]').click(function () { 107 self.remove(data.id); 108 }); 109 } 110 111 return item; 112 }; 113 114 Flexx.SmartList = SmartList; 115 116 }(window.xx = window.xx || {});
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 var groupList = new xx.SmartList('#groupList', { 33 isDeletable: false, 34 isEditable: false 35 }); 36 // 调用原型方法更新数据 37 memberList.setData(members); 38 groupList.setData(groups); 39 40 $('#btnAdd').click(function () { 41 memberList.add({ 42 id: 4, 43 title: 'add', 44 content: 'hi' 45 }); 46 }); 47 48 }); 49 50 }();
总结:
1、要尽量减少代码重复;
2、充分利用回调函数。
3、一个关于布尔值的知识点:
任意javascript的值都可以转换为布尔值,下面的6个会转换为false:
undefined、null、0、-0、NaN、""//空字符串,其他值,包括对象(数组)都会转换成true。