一次项目重构
上学期由于期末停工的项目又要继续开展了,然而停了一个多月的时间,我已经看不下去他的代码了,简直惨不忍睹,花了我将近40个小时的时间去做了重构。虽然重构说明有进步了,但是一改就要改几十个页面啊…累觉不爱..说一说这次将近40小时的重构吧。
Angular 重构
项目是基于 Angular 的 SPA,项目参考Angular规范进行重构,主要是以下几点:
- 把控制器的业务逻辑(主要是 HTTP 请求)分离到 Factory
- Controller 和 Directive 以及 Factory 全部用立即函数包装
- Controller 和 Directive 以及 Factory 内部书写格式
- 使用 controllerAs 代替 $scope
- 全部 JavaScript 文件使用 use strict 严格模式
- 利用单体做部分数据的缓存
- 提取大部分可复用模块到 directive
- 全部 ng-repeat 加上 track by
- 过大的试图使用 ng-include 进行分离
- 去掉全部辅助变量,用 angular-promise-buttons 来达到按钮状态变化
- 去掉全部页面切换动画
- 手动进行依赖注入
- 使用 ES6 语法,用 babel 转为 ES5
- 使用 eslint 来做代码格式检查
之前我几乎没有使用 Factory 这一层,全部业务逻辑都在 Controller 里面做,随着项目越来越大(有26个页面),页面之间函数重复的情况很多,而且控制器太厚,可读性差,给维护带来了巨大的困难。在这次重构之中,我把全部的 HTTP 请求全部放在 Factory 实现,从而做到了以下几点:
- 函数复用,多个控制器用一个 Factory,避免同个函数多次书写
- HTTP 请求返回 promise,结合 angular-promise-buttons 做到了按钮状态的自动变化以及过渡效果,去掉了先前实现同样目的的全部辅助变量
- 对部分相对不变的数据,在第一次缓存后直接在该 Factory 进行缓存,第二次获取的时候直接返回内存中的数据,加快了部分页面的二次加载速度,对跨页面你的同个请求同样有效
- 容易做单元测试和更改逻辑,因为全部 HTTP 请求都放在 Factory 实现,对后期修改以及代码测试都带来了很大的方便
举个例子,这是我项目中的部分代码,现在是能拿出手了,以前的代码我都不能再吐槽了
|
|
然后是 Factory 文件
directive 就不给示例了,上面主要参考了这个Angular规范。这样写真的比我之前写的好了几百倍,controller 和 factory 和 directive 都按这个规范来,代码会很好维护。
这次重构让我知道我以前写的根本不叫 Angular,写的是一坨翔,MLGB 害我改了四天。
HTML 重构
其实说白了也是 Angular 重构,在上面的 Angular 重构已经提到了一些了,但是上面主要是说 controller 和 factory,这里说下 directive 和视图。
部分页面复用
在 Angular 中,HTML 部分复用有两种方案,一种是使用 ng-include,还有一种是使用 directive,其实区别很简单,ng-include 只是很简单的 HTML 复用,而 directive 你可以传递参数,directive 可以有自己的控制器,可以操纵 DOM,其实就是 HTML 和 JavaScript 文件的区别。不过这只是 directive 在页面复用这一块的作用,其实 directive 强大的很。
使用 ng-repeat 都带上 track by
对于 ng-repeat 使用 track by 可以提升性能,对于任何 ng-repeat 都加上 track by 是一个好习惯。比如
也可以直接使用 track by $index。
使用 controllerAs
直接在路由使用 controllerAs
然后在视图中就像上面的例子,在访问控制器的变量和方法的时候都要带上 vm,虽然这样会稍微麻烦了一点,但是可以避免很多坑,而且这种写法更接近 JavaScript 原生的写法。
CSS 重构
恩,CSS 重构才是真正的大坑,先说下我之前是怎么写 CSS 代码的
- 使用了 Sass 预处理器
- 多层嵌套
- 命名混乱
- 过多复用
- 全部挤在一个文件
恩,挤在一个文件里面是最要命的,而且很任性的进行嵌套,导致多了或者少了一层都可能出问题,而且是2000多行的代码…所以我其实并没有做什么重构,我把它从一个文件分成了很多个文件,每个视图一个专属 scss 文件,对于复用的部分页面,用 directive 替代,并给该 directive 专属的 scss 文件。
怎么做到专属呢,就是每个视图和每个 scss 都包装在一个类名里面,这样就保证了 scss 代码互不干扰。
所以,其实我做的只是便于后期书写而已,总不能继续在这个文件书写下去,大坑啊。。