模块化的前端开发 — OOFE
在 webrebuild 年会北京站,蒋定宇 分享的模块开发对我的影响不小,也做了不小的尝试,觉得可取的地方很多。
既然尝试了,就分享下我对模块化的前端开发的理解吧,当做一份试验报告吧。
一,开发中的代码污染
在更新比较频繁的产品线上,项目随着时间的推移,产品的需求也就变得相当的频繁,PM需要我们前端工程师修改的地方也将变得越来越多,而这些时间里,公司的产品线中,维护代码的人可能也更替几次了,而每一个工程师要读懂以前的代码的难度也会随着产品线的时间以维护人员的更替增加而越来越大。维护一个好几手的代码,可能也不是一般新工程师喜欢的事情,大多工程师一般都会选择避过老代码而直接开发新的代码;还有就是多人一起开发时,大家每个人的代码书写习惯以及技术的参差不齐,导致很多重复功能的开发,就这样,产品线的前端走向一个到处是污染的,杂乱,重复的功能代码,参差不齐的袋子。
问题:缺少框架与文档的共同约束,没有良好的前端架构
二, HUB 和 UI Thread
hub的工作方式:

HUB是一个多端口的转发器,当以HUB为中心设备时,网络中某条线路产生了故障,并不影响其它线路的工作,也不会导致HUB故障。
重点:client个体的单一独立化,hub做为转发器,让client之间实现交互。
UI thread 的中文意思大概是 用户界面线程吧,就是指一个用户界面的前端表现线程,或者说前端代码被浏览器解释的过程?我也说不清楚,我们还是用它可意会,不可言义的名称UI Thread 来理解吧 ^ ^ 。举过小例子来说一下吧。
请看下面的代码:
<input id="btn" style="padding: 3px; border: 1px solid #ccc; background-color: #eee;" type="button" value="请猛击我" />
<script type="text/javascript">
var btn = document.getElementById("btn")l
btn.onclick = function(){
btn.style.border = "1px solid #f00";
btn.style.backgroudColor = "#f22";
}
</script>
从这个UI Thread例子中,我们知道浏览器提供了一个用于JS,CSS,HTML相互交互和通信的机制。浏览器做为一个事件派发环境,为UI提供事件的注册,初始化,和派发等。
三, 模块化开发
合并Hub 与 UI Thread 建立稳固的前端架构:
了解了Hub的工作方式以及UI Thread 后, 结构,表现,行为都各自建立一个以模块(类似 hub 中的 client)为单位切分的环境。其实就是所谓的OO,面象对象。
概念:OOCSS,Javascript模块化开发
OOCSS是最近大家关注的比较多的一个话题,提倡面向对象的开发
在OOCSS里,一个CSS对象由4部分组成:
- 可能是一个或多个DOM节点的HTML
- 由包含节点的class名开始的CSS样式声明
- 类似于背景图片和显示用的sprites组件
- JavaScript监听,广播及运行与对象关联的方法或行为
看一段代码:
<div class="mod">
<div class="head">
<h1>Block Head 1</h1>
<h2>Block Head 2</h2>
</div>
<div class="body">
<div class="hd">Block Head</div>
<div class="bd">Block Body</div>
<div class="ft">Block Foot</div>
</div>
</div>该对象是一个class为mod的模块。
包括4个部件节点(不能独立于模块外,包括3个区块,head,body,foot,在模块开发中head和foot属于可选择的区块)。
OOCSS的性能提升:
- 高度重用的CSS代码,只需要很少的CSS代码,意味着:
- 更小的文件,从而更快的传输
- CSS代码在站点页面中调用的比重增大则有希望被复用或被浏览器缓存
- 就浏览器而言更少的重绘和布局计算
- 单个页面,CSS规则复用的越多,渲染引擎花在“computed values”的计算时间越少
- 手动增加的”extending”类,重写更少的规则,这再一次意味着引擎做很少去应用规则
对于具有特性的对象,你要可以使用ID定义样式,比如非常特殊的header menus,此时你可以在用ID来扩展对象的专一性。
Javascript模块化开发:
这个已经是很多库都在做的事情了,但是在这里提到的Javascript模块化开发是指建立一个OOCSS中的对象间相互跨模块或者说跨对象交互通信,以OOCSS对象为对象的开发模式,模仿UI Thread 编写单一模块(对象) 的线程:

还是拿类似于蒋定宇提到的那个例子来说明下吧!
例子页面:猛击此处>>

采用Hub的工作方式以及UI Thread 实现这两个模块间的交互:
图片展示模块(对象)的代码如下: [ 我把这实现模块交互的Hub取名为VUI ]
/* * 图片展示模块 * @param {String} Module Name * @param{Object} Module */ VUI.add("photo-show-icon", { //模块初始化:监听img-src-change命令 init: function(mod){//传入当前mod mod.listen("img-src-change"); }, //信息处理:接受到img-src-change命令时,更新UI onmessage: function(eventType, data){ switch (eventType) { case "img-src-change": this.updateUI(data); break; } }, //更新UI函数 updateUI: function(data){ var img = "<img src='" + data + "' width='100%'/>"; document.getElementById("photo").innerHTML = img; } });
这个模块(对象)的行为层就写出来了,他本身决定了他能干什么,如何交互,是一个独立的对象。
联合OOCSS与上面的模块(对角)行为层来看前端开发中的模块对象:
- 模块(对象)的功能是完整的,非片段且独立的。
- 每个模块(对象)拥有自己的html,css,javascript
- 一个模块(对象)放到页面中,不会改变其它对象的表现,结构以及行为
- 一个模块(对象)被移除了,不会对其它对象构成影响,支持热插拔
- 一个模块(对象)可以做单元开发,单元测试,可以独立工作。
- 不同的开发维护人员,开发维护过程中只针对模块(对象)进行开发和维护,且开发不会对其它对象造成影响,出现污染代码的概率较少。
对于模块(对象) hub 环境的实现,需要一个底层的对象线程处理,我这里实现了一个比较简单的实现库,取名VUI 。
上面的图片切换显示模块就是根据这个库实现的:
代码在这里:请猛击些处>>
四, 模块化开发的优化处理
模块(对象)化开发产生的问题:
- 因为开发中是基于对象开发的,每个对象建立独立的文件,实现通过组合模块(对象)来组建一个页面文档。必会产生多的css与js的引用,从而导致页面过多的请求数。
- Javascript各模块(对象)是独立的,需要一个Hub使他们通过互相交互通信
问题的解决:
- 多文件的问题,使用文件合并压缩,css sprite等技术可以完美解决。
- Javascript 各模块的交互通信,可以依据产品开发一个底层的事件派发环境来实现,如上我提到的比较简单的实现库:VUI。
报告到此结束:猛击下载查看图片展示例子的全部开发文件>>













