在前端的富应用开发领域,也称为单页应用,常用的目录划分方式有按照职责或按照功能模块进行划分
按照职责
app
+ /model
+ /view
+ /controll
+ /router
+ /lib
+ app.js
按照功能模块
app
+ /admin
+ view.js
+ controller.js
+ router.js
+ model.js
+ /login
+ ...
以上两种方式各有利弊,按照职责划分,能够比较清晰的看出整个目录的结构,但是当应用比较庞大的时候,每个职责内部可能存在大量的文件,同时由于文件的依赖并不是按照职责来划分,在维护上会产生较大的查找成本,而按照功能划分则正好相反.因为文件的依赖是按照功能来划分,所以页面的多少不会产生一个维护上的困难,造成的问题主要是目录整体结构不清晰.
有同学会说,既然如此就把两者结合一下不就行了?app /page /admin +view.js +... /lib app.js
通过提供一个page的容器层来隔离大大小小的功能模块,这算是一种混合方法,但无论上两种还是这三种方法都不能解决的一个问题是,通用功能或模块的抽象.譬如 admin 下有一个函数或者ui要被其他模块公用了,通常我们会这么做
app /common +public-view.js /page /admin +private-view.js /lib
这看起来不错,但是随着开发不断推进,需求不断变化最后可能变成这样
/common +public-view1.js +public-view2.js +public-controll.js +public-model.js +public-function.js +public-ui.js
结果显而易见,这种随着业务推进而不断重构的目录划分方式所导致的问题就是公用代码的管理困难,造成这个问题的根本原因在于,我们一开始就没有用写代码的方式去设计一个目录,或者说缺少最基本的目录划分方式,基于这点我得到了这张图
上图中关于目录层级的部分,可能大家会觉得很熟悉,尤其结合上面的结构图,就会发现 page 其实作为app的子类来定义的,没错,这里我用了继承的方式来设计目录结构,用代码来说明就类似这样
page extends app mod extedns ui
因为page是app的子类,所以page继承过的来的目录 mod store ui 都可以被轻松的转移到父类中去,用代码说明类似如下
//a页面中有一个私有的mod page ->a ->mod //现在b页面也想用这个mod,于是我们把这个mod挂载到page的父类上也就是app app -> mod //于是现在b就能使用这个mod了
基于这种划分的思想,无论应用的页面多么复杂,本质上来讲依然只是app的一个子类扩展了page.js和router.js两个文件而已.这样我们就不用为了如何去思考文件该放哪,一个私有模块变成公有了该怎么办这些头疼的问题了,同时我对目录下的文件也做了简单的定义,确保目录之间是非耦合的关系.
mod: 等于依赖外部数据的ui
ui: 不依赖外部数据就能自我实现的页面元件.
store: 数据接口
common: dom无关的函数
当然我们所用的框架以及技术架构都不一定相同,所以基于这套简单的目录结构就可以进行编程一样的扩展,从而降低维护成本.