设计想法
- 业务系统由若干个页面构成;
- 每个页面由若干个组件构成;
- 页面指的是一个比较大范围的功能模块,比如:监控、统计、设置;
- 组件是相对独立,可复用的功能实现,比如:地图监控组件、统计报表组件、车辆对话器组件。封装粒度需要根据实际情况伸缩,可以再往下细化到与业务流程无关,只被动提供类似服务的功能,比如:输出报表组件,分页组件;也可以上升到一个大的组件,比如:人员监控GIS显示,包括报警查看,轨迹查看;
- 组件的组合就是页面;
- 系统有若干个角色,不同的角色对应不同的组件组合,并且可配置;
- 原则上,所有界面都是组件的组合,系统设置的默认的角色对应的界面并不是固定的,而是由系统初始化配置时按照以上的规则配置成默认的形式;理论上也是可以重新配置的。因此,本身定位某角色想要看其他角色的功能时,只需要给该角色添加想要看的功能对应的组件或者组件组合;
- 组件与组件之间有交互关系,实现上以事件形式体现,具体的事件专门设计事件机制。主要要求各组件可以自定义自己的事件,事件对应的内容,事件发布(通过发布,让其他组件能得到该事件,参考:Twitter flightjs框架);
- 组件的基本属性:
- 名称
- 描述
- Id
- 宽度
- 高度
- 定位坐标位置(left、top)
对框架的要求
- 页面上的元素以模块形式存在
- 模块负责页面某一区域的数据加载、显示、交互、操作
- 模块内有生命周期,在生命周期内实现业务功能
- 模块以事件的形式对外通信
- 事件必须统一可以管理
- 模块的事件必须通过一种方式告知外部有哪些事件
- 页面可以加载布局,在布局内通过HTML决定布局
- 模块可以嵌套,可以很大(接管body),也可以很小
- 模块文件必须包含在一个文件夹中(js、html、css文件最好在一起,后续的皮肤等可能会影响到css文件的存放、可适当调整
- 二级页面只是模块的切换
- 模块由路由驱动,且带有参数传递到模块
- 一个hash路由会影响到页面多个模块的变化
- 为了管理系统配置,可以参考注册表的形式
- 菜单也是可配置的。不同的业务场景有不同的菜单。不同的用户的菜单如果跟权限有关,就需要通过权限再筛选一遍;
运行流程设计
- 程序启动,index.html只有body标签;
- 加载第一个模块viewport,它负责整体布局,viewport模块根据用户选择,加载不同的布局html模板;
- 根据布局html模板里定义的模块声明标签,在指定的位置实例化模块组件,并调用模块组件的init方法,模块组件在该方法内部完成自己内部的逻辑(主要是负责加载数据、显示、添加交互、注册事件);
- 导航菜单模块,根据配置+权限显示菜单项;
- 首页聚合模块,根据用户选择,加载不同的信息显示模块;
- 二级业务页面,匹配到唯一路由,通过路由跳转;
flight js框架
缺少什么
- 事件的管理;
- 数据模型的确定;
- 组件的ID确定;
- 组件内部文件的组织规划;
- 路由的进一步完善(事件分发);
- css样式文件的组织规划;(优化)
缺点
- 获取数据通过数据组件的形式,但是其实获取数据很多地方是需要用到同步的方式,所以使用场景受限。
- 事件名的平面化导致事件的区分会互相干扰;
优点
- 基于jquery dom的事件驱动;
- 组件概念;
已经完成的
- 通过组件的形式包装界面代码;
- 通过事件完成解耦;
NETJ框架
网易的NETJ框架提到的模块化开发方案 参考:http://nej.netease.com/course/topic/dispatcher/
- 垂直采用MVC架构,横向采用模块化思路。
- 模块间通过消息通信。
- 模块分为可访问模块(即我这里的页面)、私有模块(即一个页面内的子模块);
- 模块通过树的形式组织;
- 有一个统一调度器(映射到我理解的sandbox,或mediator);
- 有一个历史管理器(对应路由);
- 模块有一个UMI(即我理解的模块唯一识别符);
-
模块由css、js、html组成,但是netj的文件存放方式比较特别,它是分开放的,如下图。且它通过在html里添加两个textarea控件,指定样式和脚本;
一个前端框架需要的部分
-
模块(组件);
- 声明方式定义模块;
- 声明方式传入模块配置参数;
- 模块间通信;
- 数据获取,同步更新;
- 控件;
- 模块加载;
- 路由;
- 服务;
-
模板引擎;
angularjs
google 推出的angularjs框架。 参考:
- www.angularjs.cn/
优点
- 声明式编程(通过指令directive扩展dom能力);
- mvvm模式,让后台数据与界面几乎完全解耦;
- 优雅的依赖注入机制;
- 数据绑定,解放了界面更新代码;
缺点
- 对模块的设计不是很明确,只是简单的封装;
- 解析性能问题;
总结
以上思路主要就是一个软件设计原则(SRP\LSP\DIP\ISP\CARP, www.cnblogs.com/tomin/archi…,其中重点是:依赖倒置,针对抽象设计、而不针对具体内容设计).基于以上的思路,可以满足如下类似的要求:
- 不管什么角色,只需要设计好该角色的功能,找出现有系统是否有已实现的功能组件,若有,就复用,没有,则按照规则新开发组件;
- 产品设计的工作转化为:定义好角色的功能,并通过交互设计规划好组件之间的关系,并得出原型(该原型也是基于基本的框架设计,不能天马行空),如果认为现有规范不满足原型设计,可以考虑纳入规则;
- 开发人员不用一上来就需要熟悉所有的功能,而只需要了解原则性框架,然后开发框架代码;
- 后续各角色对应的功能可以通过增加人手,并行开发;
- 角色A可以通过添加功能组件,得到角色B的功能;
- 其他?