前端代码组织优化--小demo(进阶你的思路)
2017-04-13 16:38
232 查看
1.事出必有因
最近在看老项目的代码,一个富客户端的js代码,几千行的代码,全是function(){} var...的垂直布局,真的是要感动的哭了。一开始都是这样,想实现什么功能,不管三七二十一,function走起,最终堆起无数个变量和函数来完成一个画面的js。我也是,但过段时间自己去改代码bug或者加功能的时候,我的天,这是我写的吗,什么时候写的,怎么理不清思路了,而且,修改一个地方其他地方也得改,改完了还容易出新bug,偶尔都会忘了是自己写的,心里默念:这个傻X...恩,还好是默念。
慢慢的代码看多了点,了解了些js的模块封装的一些方式,面向对象的相关思想(单一职责、高内聚低耦合....再说就有点装了>.<),越来越觉得易读、易改的代码应该需要更好的组织形式,正好最近碰到了一个网友相关的问题,看了他想优化的代码,真有看到自己一开始写的代码的感觉:各处填补想完美解决问题,可最后还是会有出乎意料的bug,于是用了他的代码做了次实践。
2.一睹为快
如下图,功能比较简易:选择之后添加,展示区便陈列:
<!-- 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>
组织后的版本
更改后的版本里的代码其实都是原来的代码,但组织后的效果是:事件统一绑定(bindEvent),画面统一更新(fun1、fun2、fun3),数据统一设定(updateData)。
区分的很清楚,哪儿出错找哪儿,几乎不会交叉。而且比较容易拓展,像事件可以继续bindEvent绑定,画面更新的函数可以相应与fun1、fun2、fun3并列添加,数据的额外处理可以添加到updateData里。
这仅仅是代码组织上的优化,其实代码本身也有很多可以改进的地方,像全选的判定、选择区联动删除等都有更好的思路和代码实现。
5.梦中初醒
渐渐发现,其实这里面已经有mvc的影子了,各司其职,分工明确,事件绑定那部分就算是一个弱controller,绑定事件,分发事件响应函数;更新画面状态部分相当于view了,更新画面;updateData更新数据部分更新的就是modle;6.醍醐灌顶
这个组织基本够用了,但它并不是真正的MVC,也不是最优组织,需要你,一语道破天机,希望有人能醍醐灌顶....顺便看看万金油的MVC模型:
就是看不懂,是不,哈哈。
相关文章推荐
- 前端代码组织优化--小demo(进阶你的思路)
- 请教提高代码编写组织能力代码优化、精明
- [JavaScript] JavaScript进阶系列 - 使用require高效组织代码结构
- GitHub 上一份很受欢迎的前端代码优化指南
- 前端页面卡顿?或是DOM操作惹的祸,需优化代码
- 前端页面卡顿?或是DOM操作惹的祸,需优化代码
- [转] 面向对象软件开发和过程(五)优化代码的组织
- Web前端开发学习3:SEO代码优化
- Web前端开发最佳实践(12):JavaScript代码中有大量写死的配置数据?这些数据难以维护,你需要合理组织这些数据
- 由一段代码谈前端js优化和编码规范(一)
- 前端代码性能优化工具
- web前端性能优化进阶路
- 玩转SSH--Hibernate(二)---使用注解,优化代码(对demo1的优化)
- 用选择的方式对数组进行排序,并写出对应的优化后的代码实现。(重点写思路、原理)
- 由一段代码谈前端js优化和编码规范
- 基于ASP.NET提搞网站访问速度的优化后台代码与前端做哪些优化
- 用冒泡的方式对数组进行排序, 并写出对应的优化后的代码实现。(重点写思路、原理)
- 从代码方面来探讨前端优化的方法
- 前端性能之js代码优化点
- Web前端开发学习3:SEO代码优化