看到代码的那一刻我惊呆了,就一个js文件,接近2000行的代码。这个还好,比这个行数多的我见的多了,这个还吓不到我。有哪些问题,一会再说。

  因为从我接手的那一刻算起,几天后就要发新版本,我只要也只能调一些样式。代码重构,想都不要想,有想法我也得掐死。

  我以为很简单,很快就能完成,too young too naive,上代码:

  .hover(function(){

  $("").css("border-top", "1px solid #5589d4");

  $("").css("border-bottom", "1px solid #f4f4f4");

  $("").css("border-left", "1px solid #5589d4");

  $("#").css("border-right", "1px solid #f4f4f4");

  $("#").css("border-left", "1px solid #e3e3e3");

  $("#").css("border-right", "1px solid #5589d4");

  });

  文件内大量的这种内联样式写法,是不是很666,而且好多地方的内联样式代码还是重复的,我要是直接在上面改,能累死烦死。

  基于样式表现和行为逻辑分离的原则,慢慢改吧,还好,慢慢调,两个工作日基本完成了。

  ok,提交测试,没问题。(http://m.0813sy.com)

  but,两天后,兄弟组在四级详情页新增的浮层抽奖效果,插件对其有影响,查代码

  //是这样

  $('.nodata').hide();

  //以及这样

  $('.no-text').hide();

  插件第一原则,never and never 影响或更改原有页面的结构、行为。

  还好没有对外推,要不用户分分钟把插件卸了。所以临时改成了这样

  //是不是区别不大?但是重复率低啊

  $('.chm-x-nodata').hide();

  作为一个有轻微代码洁癖的人,当时我就想,有时间我一定把丫重构了。

  不过理智告诉我,先这么着吧,千万不要再来新版本了,这是一个大坑。

  重构

  墨菲定律,该来的还得来。

  这次是大改版,增加对某网站的支持。

  ok,这次时间足够了,重构。

  1. 根据业务将js文件拆开,用gulp构建。

  项目目录结构如下:

  -plugin

  -- build

  ---- chrome //chrome插件模块

  ---- plug //内容

  ------ dist

  --------- js //生成的js文件,包括.min.js

  ------ css //原来的css文件

  ------ images

  ------ js //其他js

  -- js_src

  ---- 01-x.js //公共变量、方法

  ---- 02-mod.js //模块化机制封装

  ---- .....js //子逻辑

  ---- 90-main.js //主要逻辑

  ---- 99-init.js //入口文件

  -- gulpfile.js

  -- package.json

  有意思的是,插件对象(x)内部定义了require、define对象,我以为是采用了模块化机制,实际上就是使用了一层皮。

  (function(x) {

  x.mod={};

  //构建模块化机制

  var defined = function(name, module) {

  x.modules[name] = module;

  }

  var require = function(name) {

  var m = star.modules[name];

  if (!m) {

  return null;

  } else if(typeof m === 'function'){

  //对象已实例化,直接返回

  m = m.call(m);

  }

  return m;

  }

  x.mod.defined=defined;

  x.mod.require=require;

  })(x);

  2.通用变量及方法的定义

  上面已经提到了,DOM操作用$,很容易误操作页面DOM。

  //因此在`01-x.js`中,对其进行封装。

  var x=(function(win){

  var _x={

  modules:{}

  };

  _x.$=function(str){

  if (str === 'body' || typeof str === 'object') return $(str);

  //对根DOM要添加此类

  return $('.x-root').find(str);

  }

  })(window);

  //调用

  (function(x) {

  'use strict';

  var require=x.mod.require,defined=x.mod.defined;

  var qs=x.$;

  //这样对页面的影响几乎降到了最低。

  var m=qs("http://www.zgsy0813.com");

  })(x)

  另外locastorage也未做封装,loginID、password居然直接存,是不是醉了。

  /**

  * @description 封装localStorage对象,防止对外暴露

  */

  if (!localStorage.getItem('x')) localStorage.setItem('x', JSON.stringify({}));

  x.getItem = function(key) {

  return JSON.parse(localStorage.getItem('x'))[key];

  };

  x.setItem = function(key, val) {

  var o = JSON.parse(localStorage.getItem('x'));

  o[key] = val;

  localStorage.setItem('x', JSON.stringify(o));

  };

  由于线上和测试的请求链接不同,原代码是用${x-Base-link}占位,上线前,测试时,都要批量替换,累不累啊亲。直接在配置文件中定义好就可以了啊。

  3.其他代码的整理

  封装的ajax有同步的也有异步的方法,用的很混乱。居然有三种定义。。。

  //为了代码统一,全部采用异步

  //实际上用$.ajax更好,拼接url很讨厌。

  (function(x) {

  'use strict';

  var qs=x.$;

  var require=x.mod.require,defined=x.mod.defined;

  //工具模块

  defined('Tool', function() {

  return {

  //统一使用异步

  xHttpRequest: function(url, callback) {

  return this.xHttpRequest_yb(url,callback);

  }, //封装ajax操作---异步

  xHttpRequest_yb: function(url, callback) {

  var xhr = new XMLHttpRequest();

  xhr.open("GET", url, true);

  xhr.onreadystatechange = function() {

  if (xhr.readyState == 4) {

  callback(xhr.responseText);

  }

  }

  return xhr.send();

  },

  xFalseHttpRequest: function(url, callback) {

  return this.xHttpRequest_yb(url,callback);

  },

  );

  )(x);

  代码混乱,如DOM绑定事件居然有写在ajax内或同步的ajax后的。

  冗余的代码非常多

  //如判断对象为空的这种写法多次出现

  if(x.userId == "" || x.userId == null || x.userId == 'null')

  //封装一下就好了呀

  function isNullOrEpmty(str) {

  return !str || str == ' ' || str == 'undefined' || str == 'null';

  }

  //另外同样的事件绑定,只是因为一两处逻辑的不同,居然又重新绑定了两次,代码只是更改了一点点啊

  结语

  有了基本的脉络后,实际上重构很快,三天多一点的时间就搞定了。坑填的差不多了,如若以后他人接手,希望坑不多。(逃

  对了,最后附一下gulp.js文件,一些童鞋可能还没有接触过。

  // 引入 gulp及组件

  var gulp = require('gulp'), //基础库

  jshint = require('gulp-jshint'), //js检查

  uglify = require('gulp-uglify'), //js压缩

  rename = require('gulp-rename'), //重命名

  concat = require('gulp-concat'), //合并文件

  clean = require('gulp-clean'); //清空文件夹

  var jsDst = './build/plug/dist/js';

  var jsSrc='./js_src/*.js';

  // js处理

  gulp.task('jsTask', function() {

  gulp.src(jsSrc)

  .pipe(jshint())

  .pipe(jshint.reporter('default'))

  .pipe(concat('dist.js'))

  .pipe(gulp.dest(jsDst))

  .pipe(rename({ suffix: '.min' }))

  .pipe(uglify())

  //.pipe(livereload(server))

  .pipe(gulp.dest(jsDst));

  });

  // 清空图片、样式、js

  gulp.task('clean', function() {

  gulp.src(jsDst, {read: false}).pipe(clean());

  });

  // 默认任务 清空图片、样式、js并重建 运行语句 gulp

  gulp.task('default', ['clean'], function() {

  gulp.start('jsTask');

  });

  // 监听任务 运行语句 gulp watch

  gulp.task('watch', function() {

  gulp.watch(jsSrc, function() {

  gulp.run('jsTask');

  });

  });

JavaScript项目重构到底有多少坑要填要踩的更多相关文章

  1. 【转】vue项目重构技术要点和总结

    vue数据更新, 视图未更新 这个问题我们经常会遇到,一般是vue数据赋值的时候,vue数据变化了,但是视图没有更新.这个不算是项目重构的技术要点,也和大家分享一下vue2.0通常的解决方案吧! 解决 ...

  2. iOS基于MVC的项目重构总结

    关于MVC的争论 关于MVC的争论已经有很多,对此我的观点是:对于iOS开发中的绝大部分场景来说,MVC本身是没有问题的,你认为的MVC的问题,一定是你自己理解的问题(资深架构师请自动忽略本文). 行 ...

  3. 转:iOS基于MVC的项目重构总结

    转:http://www.cocoachina.com/ios/20160519/16346.html 关于MVC的争论 关于MVC的争论已经有很多,对此我的观点是:对于iOS开发中的绝大部分场景来说 ...

  4. 把VSO作为GitHub上JavaScript项目的免费CI服务器

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:微软变得更加开放后,走向开放的不仅有.NET运行时.IDE工具,还有ALM服务器核心组 ...

  5. 【WS-Federation】到底有多少公司在用WS-Federation

    到底有多少公司在用WS-Federation? sso先调用一个登录接口 获取一个token 然后再调用各种业务接口 如果是ssl token 直接暴露就行了 没有ssl 最好每次取一个token, ...

  6. JavaScript 项目构建工具 Grunt 实践:安装和创建项目框架

     Grunt 是一个基于任务的 JavaScript 项目命令行构建工具,运行于 Node.js 平台.Grunt 能够从模板快速创建项目,合并.压缩和校验 CSS & JS 文件,运行单元测 ...

  7. Windows Store Javascript项目使用高德地图、谷歌地图、百度地图API

    原文 Windows Store Javascript项目使用高德地图.谷歌地图.百度地图API 在Win8 Store 项目中可以使用的地图主要有微软的Bing Map,目前高德地图sdk也支持Wi ...

  8. Win10系列:JavaScript 项目模板和项模板

    使用Visual Studio 开发Windows应用商店应用时,通过其提供的模板可以帮助我们快速地创建一个应用.其中,在新建一个Windows应用商店应用程序项目时可以在项目模板中选择所需要的模板类 ...

  9. Java面试中遇到的坑【填坑篇】

    看到大家对上篇<Java面试中遇到的坑>一文表现出强力的关注度,说明大家确实在面试中遇到了类似的难题.大家在文章留言处积极留言探讨面试中遇到的问题,其中几位同学还提出了自己的见解,我感到非 ...

随机推荐

  1. Vue -- 数据监听

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 【原创】大叔经验分享(34)hive中文注释乱码

    在hive中查看表结构时中文注释乱码,分为两种情况,一种是desc $table,一种是show create table $table 1 数据库字符集 检查 mysql> show vari ...

  3. μCUnit,微控制器的单元测试框架

    在MCU on Eclipse网站上看到Erich Styger在8月26日发布的博文,一篇关于微控制器单元测试的文章,有很高的参考价值,特将其翻译过来以备学习.原文网址:https://mcuone ...

  4. Java之动手动脑(三)

    日期:2018.10.12 星期五 博客期:017 这次留了两个动手动脑作业!我需要一个一个来说!先说第一个吧! Part 1 :随机生成1000个随机数 代码: //以下为 RandomMaker. ...

  5. Python基础之递归函数与二分法

    一.递归函数 定义: 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 我们来举个例子吧,比如:有个人问“egon”年龄,他说比“小大”大5岁,“小大”又说比“小保 ...

  6. hdu4064 三进制状态压缩 好题!

    还不太会做这类题,总之感觉有点难啊. 用深搜代替打表求出一行所有的可行状态,注意要进行剪枝 这是自己理解的代码,但是tle了 #include<bits/stdc++.h> using n ...

  7. cf1110F 离线+树上操作+线段树区间更新

    自己搞的算法超时了..但是思路没什么问题:用线段树维护每个点到叶子节点的距离即可 /* 线段树维护区间最小值,每次向下访问,就把访问到的点对应的区间段减去边权 到另一颗子树访问时,向上回溯时加上减去的 ...

  8. CF 1042F

    玄学贪心... 题意:给出一棵树,要求将他的所有叶节点分成最少的组,且在每组中的任意两节点之间的距离不大于k 解析: 显然是个贪心啦... 稍微考虑一下贪心思想: 我们从下向上合并整棵树,在合并到某个 ...

  9. MySQL数据库权限分类

    一.权限表 mysql数据库中的3个权限表:user .db. host 权限表的存取过程是: 1)先从user表中的host. user. password这3个字段中判断连接的IP.用户名.密码是 ...

  10. beego获取用户请求参数的方法

    我们经常需要获取用户传递的数据,包括 Get.POST 等方式的请求,beego 里面会自动解析这些数据,你可以通过如下方式获取数据: GetString(key string) string Get ...