JavaScript项目重构到底有多少坑要填要踩
看到代码的那一刻我惊呆了,就一个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项目重构到底有多少坑要填要踩的更多相关文章
- 【转】vue项目重构技术要点和总结
vue数据更新, 视图未更新 这个问题我们经常会遇到,一般是vue数据赋值的时候,vue数据变化了,但是视图没有更新.这个不算是项目重构的技术要点,也和大家分享一下vue2.0通常的解决方案吧! 解决 ...
- iOS基于MVC的项目重构总结
关于MVC的争论 关于MVC的争论已经有很多,对此我的观点是:对于iOS开发中的绝大部分场景来说,MVC本身是没有问题的,你认为的MVC的问题,一定是你自己理解的问题(资深架构师请自动忽略本文). 行 ...
- 转:iOS基于MVC的项目重构总结
转:http://www.cocoachina.com/ios/20160519/16346.html 关于MVC的争论 关于MVC的争论已经有很多,对此我的观点是:对于iOS开发中的绝大部分场景来说 ...
- 把VSO作为GitHub上JavaScript项目的免费CI服务器
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:微软变得更加开放后,走向开放的不仅有.NET运行时.IDE工具,还有ALM服务器核心组 ...
- 【WS-Federation】到底有多少公司在用WS-Federation
到底有多少公司在用WS-Federation? sso先调用一个登录接口 获取一个token 然后再调用各种业务接口 如果是ssl token 直接暴露就行了 没有ssl 最好每次取一个token, ...
- JavaScript 项目构建工具 Grunt 实践:安装和创建项目框架
Grunt 是一个基于任务的 JavaScript 项目命令行构建工具,运行于 Node.js 平台.Grunt 能够从模板快速创建项目,合并.压缩和校验 CSS & JS 文件,运行单元测 ...
- Windows Store Javascript项目使用高德地图、谷歌地图、百度地图API
原文 Windows Store Javascript项目使用高德地图.谷歌地图.百度地图API 在Win8 Store 项目中可以使用的地图主要有微软的Bing Map,目前高德地图sdk也支持Wi ...
- Win10系列:JavaScript 项目模板和项模板
使用Visual Studio 开发Windows应用商店应用时,通过其提供的模板可以帮助我们快速地创建一个应用.其中,在新建一个Windows应用商店应用程序项目时可以在项目模板中选择所需要的模板类 ...
- Java面试中遇到的坑【填坑篇】
看到大家对上篇<Java面试中遇到的坑>一文表现出强力的关注度,说明大家确实在面试中遇到了类似的难题.大家在文章留言处积极留言探讨面试中遇到的问题,其中几位同学还提出了自己的见解,我感到非 ...
随机推荐
- JS知识点随笔
1.为什么 0.1 + 0.2 != 0.3? 原因: 因为 JS 采用 IEEE 754 双精度版本(64位),并且只要采用 IEEE 754 的语言都有该问题. 我们都知道计算机是通过二进制来存储 ...
- struts2 过滤器和拦截器的区别和使用
java web 过滤器和拦截器的区别和使用 1.1 什么是拦截器: 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然 ...
- 不能够连接到主机(名称为localhost)上的MySQL服务”
不能够连接到主机(名称为localhost)上的MySQL服务” -如果是服务未启动.那么就右键‘计算机’---->管理--->服务和应用程序---->服务,在右侧的栏目中找到名称为 ...
- CSS在线字体库,外部字体的引用方法@font-face
@font-face是CSS3中的一个模块,他主要是把自己定义的Web字体嵌入到你的网页中,随着@font-face模块的出现,我们在Web的开发中使用字体不怕只能使用Web安全字体,你们当中或许有许 ...
- flask 面试题
1,什么是Flask,有什么优点?概念解释Flask是一个Web框架,就是提供一个工具,库和技术来允许你构建一个Web应用程序.这个Web应用程序可以是一些Web页面,博客,wiki,基于Web的日里 ...
- J2SE基础小结
1. 九种基本数据类型的大小,以及他们的封装类. 类型 基本类型 大小(字节) 默认值 封装类 整数型 byte 1 (byte)0 Byte short 2 (short)0 Short int 4 ...
- 按照勾选 删除表格的行<tr>
需求描述:有一个产品列表,有一个删减按钮,点击删减按钮,按照产品勾选的行,删除产品列表中对应的行数据 代码: //html代码<table id="table1"> & ...
- 分布式事务XA
1.什么是分布式事务 分布式事务就是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上.以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成 ...
- 专注笔试算法20年(C语言版)
1.C语言实现链表数据的反转({1,2,3,4}->{4,3,2,1}). int trav(PNode *head){ PNode p_1,p_2,tmp; //判断参数是否有效 if(*he ...
- 步步为营-74-Request,Response和server的其他成员
Request 1 Request.UrlReferrer 获取请求的来源 2 Request.UserHostAddress 获取访问者的IP地址 3 Request.Cookies 获取浏览器发送 ...