《开源框架那些事儿22》:UI框架设计实战
MVC中Model提供内容给UI进行渲染,用户通过UI框架产生响应,一般而言会由控制层调用业务逻辑进行处理。并把处理结果以Model方式返回View,再次渲染。UI框架的大致过程就是如此。按实现方式能够分为RIA和瘦client方式,眼下基于B/S的瘦client方式比較流行。
UI框架套路上非常easy,可是想要做好可就不easy了。眼下基于MVC的框架灿若繁星。不客气的说是个软件公司就有自己的技术框架,技术厉害的公司可能还有几套。笔者也经历过多家互联网公司,也用过不少框架。界面开发始终是短板所在。
一、新UI框架的需求由来
1. 场景A
UI框架对View层没有封装或者支持有限。
View层的代码所有须要开发者手动完毕,框架没有提供代码封装或者相关代码生成工具,导致项目开发流程中,出现大量Ctrl+C、Crtl+V,进而影响界面代码质量。
笔者曾和IT业界比較有名的外包公司合作过项目,一个JSP页面四、五千行代码,Java业务逻辑、html布局和css样式糅合在一起。不要说改动了。就是看明确页面也是异常艰难。跟开发者沟通了解到。团队採用界面实现方式是jsp。框架提供的样式不满足客户需求。迫使团队自行开发非常多框架层面的功能。常常一个需求变动,导致开发者改动十几处地方,页面的混乱就可想而知了。
2. 场景B
技术框架分层严格。界面全然组件化。View层和Model层全然分离。开发者编写页面须要额外学习组件,訪问后台成本巨大。非常多业务需求须要通过框架升级方式才干解决,时间浪费严重。
这是从一个极端走到还有一个极端,以严格的框架彻底限制死开发者。
笔者參与过的银行项目,就是採用这样的方式:开发者写的页面全是组件模板。无法灵活定义一些功能,导致所有业务需求全然通过组件体现,并且开发者本身无法改动组件。组件存在Bug或者无法实现某些业务场景,那开发者还要在组件团队、项目领导之间扯皮,搞得所有人身心俱疲。
3. 场景C
框架性能问题。
框架设计人员追求华丽的页面效果,完美的层次封装就easy导致这样的后果,特别是在页面复杂或者页面嵌套多时,非常easy发生这样的问题。
开发者最怕遇到这样的问题,这意味着项目要伤筋动骨。还以银行项目做样例:原先框架版本号是3.0,业务领导觉得界面太土。不美观。经过框架团队一年多的努力。框架4.0对界面做了大幅度的美化处理,提供了复杂的封装,结果造成严重的性能问题。由于银行项目页面复杂,有些表单要展示几百个字段,用框架4.0开发后要10多秒,根本无法被接受。最后这一系列的代价由开发者买单,用html原生语法又一次开发这个复杂页面。
4. 场景D
升级维护问题。有些框架设计时,设计人员迫于团队或者领导压力,框架集合太多业务逻辑,导致后期团队面临两难选择:不升级,Bug无法解决;升级界面产生各种问题,须要花费大量精力去纠正。
这样的场景也不少见,特别是框架包括多个项目的业务需求时。冲突由为明显。笔者经历过一个项目:每次升级,代码须要对照几百处,浪费2-3天的时间。就这样还不能保证全然正确。最可怕的是,每次升级都要如此。
归纳一下,对UI框架有例如以下需求:
1.提升开发效率,降低反复代码。
对于开发者而言。开发时。界面写得代码越短越好;维护时,改动的地方越少越好。
2.清晰的UI层次,框架能够分离业务逻辑、布局和样式,让页面结构清晰明了,让开发者集中很多其它精力在业务逻辑,而不是页面布局、js、css等技术细节。
3.丰富的组件支持,项目团队大部分业务场景应该能够被框架组件涵盖。而无需又一次开发。
4.灵活的扩展能力,项目团队能够依据框架规范自行扩展展示组件,实现个性化需求。
5.优异的性能。UI界面展示时的响应时间应该和原生态语言接近。框架能处理JS、CSS载入及合并的问题。
6.框架升级不影响业务代码。
仅仅有满足上述要求的UI框架,对开发者和项目团队才是真正有帮助的UI框架。
二、TinyUI的解决方式
Tiny团队对UI框架也有自己的想法。也提出一种UI框架解决方式。TinyUI採用例如以下设计原则,项目团队在技术选型时须要考虑清楚。
TinyUI的原则
1.保证界面开发的灵活性。尊重开发者的开发权利。
Tiny团队遵守“二八”原则。觉得再完美的UI框架也仅仅能解决80%实际开发过程中遇到的界面问题。剩下的20%须要开发者的经验和智慧才干解决。那种提倡一揽子解决所有界面开发问题的UI框架。仅仅会让设计者陷入过多技术细节。导致过度设计。
因此。TinyUI提供最大程度的灵活:仅仅要遵守必要的框架规范。开发者能够自由扩展组件。来满足日益变化的业务需求。
2.技术问题与业务逻辑分离。
TinyUI採用开源协议,作为开源软件来提供UI框架。代码本身不包括不论什么业务逻辑。
避免框架设计者开发业务组件,业务团队使用的模式。技术问题由设计者解决。而业务逻辑由业务团队依据自身业务灵活定制、扩展。
3.性能至上,效率优先。
TinyUI在设计初期就考虑组件性能问题,目标是接近原生态页面。其次。UI框架全然开源。开发者仅仅要熟悉模板语言,就能够轻松上手。避免由于学习曲线过高影响开发效率。
在上述原则的指定下,TinyUI具有例如以下特性:
特性
1.TinyUI是基于JQueryUI,相较于Dojo来说,JQueryUI更easy上手。使用也更简单;相对于ExtUI来说,它更轻量,速度响应也更好。同一时候它也是可胖可瘦。即能够实现比較大的控件,也能够用少量代码就使得界面更加灵动。
2.布局与界面分离。TinyUI引入模板引擎。页面採用模板+组件的方式进行渲染。能够大幅简化页面。
3.採用了多重布局方式,每一级文件夹其中都能够编写一个布局。项目经理能够依据业务需求按不同层级定义不同的布局。
4.採用了pagelet方式,能够把页面区块独立提供或者被别的页面进行引用。
5.提供了UI组件模式。用户能够方便的编写UI组件,并公布到应用其中,同一时候提供了资源载入机制,假设UI组件包括有JS或CSS文件。不用特别指定。也不用进行首页合并。可直接被使用。
6.提供了BigPipe机制。能够大大提供模板的处理速度及提升用户界面的使用体验。
7.通过组件方式开发界面,封装了组件的实现细节,能够平滑切换到其他实现。
8.与各种开源组件或代码段集成更easy。利用一个已经实现的开源组件封装成UI组件,仅仅要几分钟。接口的扩展能够循序渐进。随用随包装。
9.资源自发现。
框架会自行载入新添加的组件,全部的css/js文件都会自己主动进行加入。
TinyUI实际上并非一个详细的UI展现组件,它仅仅是一个UI构建体系。
它能够适应于各种Html+CSS+JS的体系架构中。提供以UI方式开发界面的技术方案。
组件规范
TinyUI觉得界面全部公用的内容都能够由UI组件包(UIComponents)概括。UI组件包包括一个或者多个组件(UIComponent),UI组件包中包括了其所需的css/js/gif/htm等等各种资源。同一时候有一个UI组件包描写叙述文件(*.ui.xml)。描写叙述对UI组件包的结构、内容、以及对其他UI组件包的依赖关系。
开发时,UI组件包以独立的mavenproject为单位。最后以Jar包为单位进行公布。
举例:我们要复用JQuery。实际上很easy。在Mavenproject结构中,在resources文件夹中。放置全部的JQuery资源进来。然后编写一个ui组件包描写叙述文件。UI组件包就算开发完成了。
TinyUI框架的组件管理器会依据包描写叙述文件自己主动载入、引入相关资源,而这些都无需程序人员干预。
页面规范
TinyUI推荐採用模板语言,如:tinyTemplate,FreeMaker等作为展现层,这样能够充分发挥组件包的优势。Tiny内部实现复用了tinyTemplate模板语言,可是实际上并没有限制。你全然能够用其他模板语言做相同的事情。
详细页面开发时,组件开发者採用宏定义详细的函数接口,普通开发者直接调用宏接口就能够了。
举例:
这样写页面多简单,採用Tiny框架的前台开发,基本上帮助你攻克了上述难题,可是对你的工作没有不论什么限制。
小贴士
Dojo简单介绍:
Dojo是一个用javascript语言实现的开源DHTML工具包。利用它的低级API和可兼容的代码,可以写出轻便的、单一风格(复杂)的JavaScript代码,它能提升你的web应用程序可用性、交互能力以及功能上的提高。
ExtUI简单介绍:
它是一种主要用于创建前端用户界面,是一个基本与后台技术无关的前端ajax框架。组件丰富,功能强大,可惜如今收费了。
三、TinyUI的设计思路
常见问题
1.UI中JS的引入与顺序,JS合并的问题 。
2.UI中css的引入与顺序。CSS合并的问题 。
3.反复代码的问题。
相同的内容在很多地方都有,假设要修改就要修改很多个地方,修改时万一遗留了,将来就是一个坑。
4.总体布局调整困难的问题。
5.开发效率的问题。项目经理总是期望界面开发越快越好。
6.运行效率的问题。前台响应要求速度更快。
7.国际化问题。
......
以下。笔者依次解说TinyUI是怎样处理上述问题:
Js和Css的引入与顺序以及合并的问题
1.JS和CSS的引入问题。
传统界面开发,程序猿须要在页面配置引入js和css的路径,既麻烦又easy出错。TinyUI採用组件封装了JS和CSS。这份工作统一交给组件设计者处理,程序猿开发页面时根本不用关心须要引入哪些JS和CSS,仅仅要知道要用哪些宏接口即可了。
2.JS和CSS的顺序问题。
这个问题也是传统界面开发之间的难点。JS和CSS之间的顺序搞错。一般会导致页面出现乱七八糟的问题。定位问题也是异常复杂。TinyUI将顺序问题交给组件管理器处理。它会依次检查组件的依赖关系。假设有UI组件的依赖关系配置错误,组件管理器会记录异常日志。这些不正常组件不会被载入到正常组件列表。
组件间的依赖关系理顺后,组件内部包括的JS和CSS的关系也就理顺了。
TinyUI按例如以下顺序载入JS和CSS:
a. 父组件的资源比子组件优先载入。比方组件A依赖组件B。那么框架先载入组件B资源。再载入组件A资源。
b. 同一组件的资源,顺序靠前的优先载入。组件的js和css路径都能够配置多个,同一组件框架按配置顺序依次载入资源。
3.JS和CSS的合并问题。
在传统界面开发,性能调优往往涉及到js和css的合并。页面的IO少了,性能自然能提高,可是对程序猿来说这就非常困难。修改js和css意味着非常多相关页面都要修改。
TinyUI从框架层面支持js和css的合并。程序猿无需手工调整。框架提供了UiEngineTinyProcessor这个适配器处理上述合并问题。
UiEngineTinyProcessor合并JS
a. 适配器通过组件管理器获得所有正常的UI组件。并依次遍历每一个组件
b. 调用组件的getComponentJsArray方法,获得该组件引用的所有js路径。并依次遍历每一个路径
c. 依据路径通过VFS获得js的内容,合并到outputStream
d. 合并完每一个组件的引入JS内容,最后合并该组件须要调用JS代码
UiEngineTinyProcessor合并CSS
a. 适配器通过组件管理器获得所有正常的UI组件。并依次遍历每一个组件
b. 调用组件的getComponentCssArray方法,获得该组件引用的所有css路径,并依次遍历每一个路径
c. 依据路径通过VFS获得css的内容。合并到outputStream
d. 合并完每一个组件的引入css内容,最后合并该组件须要调用CSS代码
反复代码的问题
细致分析页面反复代码的由来,主要能够分为下面几块:
1.没用的资源引入。写过页面的人都知道。程序猿最喜欢把一段段的js、css到处粘,而不分析是否实用。导致大量不必要的资源引入。减少页面性能。TinyUI通过组件管理器管理资源。终于输出到页面的引用,绝对跟组件包的资源一致,仅仅要组件设计者设计组件包时保证没有引入没用的资源。
2.反复的业务逻辑。
TinyUI採用模板语言渲染页面,通过宏定义解决反复业务逻辑。由于宏是能够嵌套宏的,所以理论上再复杂的页面都能够通过宏搞定,宏假设使用得当,能够大幅度降低页面代码。
3.同样的功能片段。 有些业务场景须要引入统一功能片段。界面同样,TinyUI能够採用模板命令include完美处理这样的场景。
总体布局调整困难的问题
传统界面开发,页面布局与逻辑代码是混在一起的,特别是复杂页面,调整起来自然困难。TinyUI的设计时一開始就将布局与页面逻辑彻底分成两个文件。当然你要用TinyUI推荐的模板组织。
Tiny的模板体系组织方式例如以下:
?支持多层文件结构
?
布局文件统一用.layout扩展名结尾
?
页面文件统一用.page扩展名结构
?仅仅有.page文件能够被外部訪问,訪问方式有两种.page或.pagelet
?
訪问.pagelet,实际上相当于訪问同名page。模板引擎仅仅会做页面渲染。訪问.page。模板引擎除了页面渲染还要进行布局渲染
或许有些人看到这里问:将一个文件内容拆分成两块。还要定义两者间的联系,是不是太复杂了?事实上一点也不复杂,用户根本不须要定义布局文件和页面文件的联系,请參考下面规范设计你的页面布局结构:
查找布局文件规则
1.匹配当前文件夹同名的布局文件。
2.匹配当前文件夹默认的布局文件。
3.若某一级文件夹无法满足匹配条件。则向该文件夹上一级文件夹进行匹配,直到根文件夹为止。
比方:aa.page所中的路径是/a/b/c/aa.page,布局的渲染步骤例如以下:
查找/a/b/c/aa.layout是否存在?假设存在,则渲染,否则查找/a/b/c/default.layout,假设存在,则渲染。
查找/a/b/aa.layout是否存在?假设存在。则渲染。否则查找/a/b/default.layout,假设存在,则渲染。
查找/a/aa.layout是否存在?假设存在,则渲染,否则查找/a/default.layout,假设存在。则渲染。
查找/aa.layout是否存在?假设存在,则渲染,否则查找/default.layout。假设存在,则渲染。
通过上面的渲染机制,程序猿有可能仅仅写了很少的内容,可是通过分层布局渲染。最后出来的效果也会很丰富多彩。
开发效率的问题
採用TinyUI框架对开发效率提升。至少有例如以下两点:
1.反复代码大幅降低。工作效率自然就提升了。
2.学习曲线减少。採用组件+模板的页面开发模式,对普通开发者基本能够屏蔽JS和CSS。这两者的技能要求程度就能够大大减少;额外添加的学习成本是模板语言,对程序猿而言。模板语言达到使用程度,一天足矣。
运行效率的问题
TinyUI框架採用例如以下技术手段,加快页面的訪问速度:
1.合并页面的JS和CSS。通过降低网络IO请求,特别是在原页面涉及非常多资源时,提速效果就会比較明显。
2.缓冲功能。用户能够设定哪些页面进行缓冲。缓冲多长时间。
3.支持BigPipe方式渲染页面。前文说过TinyUI框架支持将大页面拆分成一个个pagelet,让浏览器能够多线程同一时候渲染。从而提升性能。
普通的web页面,一般来说是页面生成,网络传输。前面页面渲染,这三部分的时间加起来就是操作人员从点击鼠标到最后看到页面的时间。
举例来说,一个页面有主页面框架,共同拥有4个部分的内容显示。为了便于分析。简化一下模型,如果主页面框架生成须要0.2S,4个部分的内容生成各自须要0.2S,网络传输与浏览器渲染也各计成0.2秒,这样。在传统的方式下,须要的时间就是0.2*5+0.2*5+0.2*5=3秒。
那么换成BigPipe方式。时间的运行分布大概是例如以下图:
![](http://bbs.tinygroup.org/data/attachment/forum/201507/08/231917g3dvf8lfhpdf2v9d.jpg)
所以换成BigPipe方式,时间大概就是1.4秒的样子。
节省的时间大概是50%强一点的样子。
当然,这个时间是在各自三段时间都是0.2秒的情况。实际执行过程中,网络传输的时间在局域网中的时间会更快,后台页面的处理,也能够採用多线程处理的方式来进行,这样,后面页面处理时间能够缩短到0.4S。网络传输时间有0.2S也能够了。因为採用了BigPipe方式。在0.6S的时候,就能够看到最页面框架,后面的时间就是一块块出来,当后面出来的时间比較快的时候,给使用的感受就是在0.6S+界面就能够出来。这个与最初的3S,用户体验上明显是有天差地别的。
国际化的问题
对于小项目而言,可能不关心这个问题。可是TinyUI好歹是技术框架,目标是大型项目,假设不能支持国际化。那也说只是去。
TinyUI提供两种国际化方案。任君选择:
1.国际化资源标签。国际化资源就非常easy理解了。project加入国际化资源文件。页面用国际化标签进行引用就可以。
2.国际化页面。 国际化页面是指訪问某页面时,模板引擎会优先使用与訪问者同样的语言的页面文件进行渲染。譬如:存在aa.page,aa.zh_CN.page,假设非zh_CN语言的人来訪问,渲染的是aa.page。zh_CN语言的人来訪问。渲染的是aa.zh_CN.page。