从Enyo看移动Web应用框架设计
文 / 程邵非
Enyo是一个来自Palm的Aries项目的JavaScript开发框架,它所关注的方向是一般的程序框架所关注的封装性、复用性和可维护性。
历史
Enyo是随着webOS发布的开发框架。
Enyo 1.0发布于HP TouchPad的webOS之上,它是依赖于WebKit的开发框架。因为一些历史原因,Enyo 1.0的授权仅限于webOS中使用,并没有使用开源协议。
Enyo 2.0则是一个跨平台的框架,它现在已经在github以Apache 2.0协议开源。
如无特别强调,本文后面所述的Enyo皆指Enyo 2.0框架。
核心概念
如Enyo网站主页强调的,Enyo的核心是一种封装模型,让使用者能够更容易地复用和维护。在这一点上,Enyo更倾向于一个传统程序设计领域的框架。它所关注的方向是一般的程序框架所关注的封装性、复用性和可维护性。
与Enyo相比,一些流行的JS框架设计的核心思想则显得不那么“程序员思维”,比如jQuery的设计理念是:Write less, do more。
jQuery在这一点上颇受一些程序员背景的工程师诟病,但恰恰因为这样,它讨好了大量设计师和有设计背景的前端工程师。
Enyo的设计理念是将程序分解为一个个的Component(组件),Component又能够由其它的Component组成。Enyo是一个立足于UI的框架,但它的Component理念并不限于UI组件。
Enyo这样的设计非常适合较大的工程,这跟传统的Web前端项目理念有些不同。很难想象一个网页会由很多工程师共同完成。而Enyo认为基于Enyo开发的应用程序,可能需要更多工程师来进行合作。
总体而言,从Enyo的整体设计看,它对于移动开发程序员和程序员背景的前端工程师比较友好,而与之相对,它对于设计师背景的前端工程师则不那么友好。
Enyo的设计目标:Web、移动、应用
Enyo作为应用程序基础框架用于webOS上,这决定了它的设计目标离不开Web、移动和应用三个关键词。
毫无疑问,webOS选择HTML+JS的开发方式很大程度是看中了已有的网页前端开发工程师资源。经过多年的发展和磨合,现在网页开发已经是一个非常成熟的技术环境了,这其中有着由设计师、工程师、产品经理等不同人才组成的完整的生态系统,大部分企业的开发流程也已成熟。尽管拥有JavaScript这样图灵完备且具有相当抽象能力的编程语言,网页与应用之间仍然有着不小的差距,而Enyo的设计目标之一就是尽量弥合这个差距。
为了与同类产品竞争,Enyo还必须要提供能够快速上手的开发能力,以及对硬件的访问能力。而这些恰恰是传统网页所缺少的功能。
Enyo的编程模型中基本抛弃了HTML语言本身,而主要使用JavaScript和DOM API来编写图形界面。Enyo选用JSON来代替HTML作为界面描述语言,这样既保持了方便的程序访问性,又保证界面编写难度不会过高。
JSON描述界面这种做法在传统的JS框架中有成功的先例,其中最为著名的当属ExtJS,Enyo选择这一做法很可能借鉴了ExtJS的成功经验。
当然抛弃HTML这一做法实际上意味着Enyo放弃了大批Web开发者以及围绕Web开发的工具。Enyo的这一选择可能并非明智。
因为webOS系统主要用于移动设备,所以Enyo的设计也必须更多考虑移动设备。Enyo提供了专门为触屏设计的Scroll组件,这样可以使webOS设备能够轻易地做出接近iOS和Android设备的触摸滚动效果。
Enyo的架构
Enyo主要分为五个模块:Kernel、AJAX、DOM、Touch、UI。
Kernel模块为所有模块所依赖,其中主要包括对JavaScript语言本身的扩展和Enyo的Type系统。
AJAX模块实际上不仅仅是AJAX功能扩展,还包括JSON等AJAX相关的功能扩展。
DOM则是对HTML DOM API的简单封装和基本手势的支持。
Touch实际上包含了Scroll和Touch功能的结合,touch提供了各个层次的Scroll逻辑,既能够直接使用Scroller,又能用更为底层的ScrollMath和ScrollStrategy来定制自己的Scroll行为。
UI模块是Enyo提供的基本控件,这些控件的主要作用是生成对应的HTML代码。
加载系统
Enyo的主要模块之外,有一部分Boot模块可以用于加载Enyo的脚本以及注册全局命名空间。
这里Enyo提供了一组简单的包管理系统,包括加载包、包依赖关系,以及样式表单文件的管理。
虽然很少用到,但这部分功能也暴露给了开发者,通过enyo.loader可以实现加载代码包并且处理依赖关系。
OOP系统
Enyo实现OOP的方式是Type+Component模式,这基本可以认为是Class和Object的别名。
Enyo的Type系统是Enyo提供的一种类型系统,一切Enyo框架内的组件都必须遵循Type系统来注册自己。
Component系统则是与Type系统密不可分的,任何Component都必须有自己的指定Type,Enyo正是通过这种方式保证模块化的。
以下是来自Enyo官方网站的一个注册类型实例。
enyo.kind({
name: ”Hello”,
kind: enyo.Control,
components:
[
{name: "hello", content: "Hello From Enyo", ontap: "helloTap"},
{tag: "hr"}
],
helloTap: function()
{
this.$.hello.addStyles(“color: red”);
}
});
值得注意的是,Enyo可以简单地将几个Component组合,形成新的Component类型。
Enyo注册类型之后,则可以直接通过new来创建Component。
在kind函数接受的JSON描述中,kind属性起到了等同于指派父类的作用。
扩展API
如同每一个JS框架做的那样,Enyo也有对XHR、Cookie、事件、异步等一些HTML DOM API做了扩展,这样可以减轻Enyo的开发者的负担。
比较特别的扩展是Enyo对于手势的封装,Enyo提供了10种手势:up、down、tap、move、enter、leave、hold、release、holdpulse、flick。这些基本涵盖了所有的单点触控手势。
scroll系统
在Enyo中最简单的支持滚动的方法是直接使用Scroller和TouchScrollStrategy,Scroller提供了基本的滚动行为,TouchScrollStrategy提供对手势的基础支持。
实际上Enyo暴露了不同层次的API,最底层的是ScrollMath类型,它定义了一个效果比较良好的滚动所用到的数学和物理常量以及算法。
ScrollStrategy则是一个抽象类,它规定了手势与Scroller之间的关系,如果不使用原生TouchScrollStrategy的话,则可以自由定义事件和滚动的触发关系。
思考
Enyo作为一个已被正式商用的移动应用开发框架,无疑是值得后来者学习的,包括其他基于Web平台的操作系统、试图为hybrid服务的Web框架以及类似PhoneGap的HTML应用壳程序。一些Enyo受到诟病之处,也值得参照和避免。
Enyo中可以总结一些移动应用框架的设计原则。
尽量保持原生风格。在框架设计上,采用颠覆性的风格是危险和得不偿失的,应当尽量贴近原生API的命名风格和设计风格。
提供多层次的API。既给初级用户提供能够简单使用的API,又给高级用户提供足够灵活的API,当两者矛盾之时,可以通过暴露不同层次的API来实现。
节省命名空间。如非必要,尽量不污染全局命名空间。
支持触屏设备。现有局面下,移动框架的主要竞争焦点在于触屏的支持,尤其是手势和滚动效果很大程度决定了框架的优劣。
考虑开发者多样性。Web App的开发者包括传统的前端人员和一部分移动开发工程师,设计框架时过于倾斜将会导致一部分开发者流失,尽量提供给用户多种选择更为合理。