Ext JS 4简介
Ext JS 4目前是Sencha的产品,4.x的正式版本号是4.0.7。Ext JS 4提供商业版本,但如果您的项目是开源的,则可以免费使用Ext JS 4。Ext JS的论坛目前非常活跃;Ext JS还在不但地升级改进,据Sencha官方统计,使用Ext JS的开发者数目在一百万以上。
Ext JS 4与之前版本的比较
清单 1. 按需加载类的例子
这个特性其实是基于全新设计的类系统的,详见下面的小结。不同于先前版本:即使用到Ext JS框架中很少一部分单元,Ext JS也会加载所有的框架,按需加载只加载需要的类。因此按需加载类为JS优化和减少内存消耗提供了一个有效途径。Sencha为此还提供了SDK工具对JS代码进行Minify,在部署前运行Minify对JS代码最小化后,将得到一个最小JS集合。
MVC的概念很简单,但实际项目中运用MVC模式将代码组织起来会不会没那么简单?答案在后面的章节“介绍开发Ext JS 4的利器 : Sencha Architect 2”中,该章节会详细介绍怎样用该工具开发MVC模式的Ext JS程序。
为什么要运用MVC架构MVC的概念
MVC是一种成熟的软件设计模式。MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式通过对复杂度的简化,使程序结构更加直观。软件系统通过对自身基本部份分离的同时也赋予了各个基本部分应有的功能。专业人员可以通过自身的专长分组:
MVC模式的特点:
运用MVC以前:
运用MVC以后:
图 1.文件结构
清单 2.入口文件
整个工程仅此一个HTML文件,供十一行,其中demo.js是工程的启动文件,里面包含了所有UI widget的构建,后面会具体介绍。
入口定义在Ext.application({...})中,这是Ext JS 4为开发MVC应用新增的函数,我们可以在里面引入初始时所需的Controller、View或Model,在launch函数中编写初始代码,和以前在Ext.onReady()中一样。因为Ext引擎会在Ext.application({...})函数执行时创建一个全局application实例并能在Controller中被引用得到 (this.application.*),所以我们也可以在application中定义一些公共函数,甚至注册一些事件,方便其它Controller调用。
"model"文件夹中只有模型相关的类定义,每个模型定义必须包含字段,还能定义字段校验规则,不同模型之间的关联,以及数据代理(连接服务器存取数据)。比如雇员\部门对应两类模型,体现为两个类文件"Employee"和"Department"。
"view"文件夹中定义了所有的 widget,每一个 widget 对应一个类文件。view 的代码属于静态代码,后面将提到怎样用工具自动生成。
"controller"文件夹中的控制器按管理范围的不同划分为不同的类文件,其中每一个控制逻辑都包括初始化、组件事件监听以及引用等。比如,导航菜单的控制器会包含对主页面菜单按钮的动作监听”click“,并在该事件中负责创建相应的子页面;而子页面对应的控制器只负责该页面中的组件的行为,如提交按钮的点击等。另外控制器本身能被动态加载,在下文的例子中我们还可以看到,不同的控制器被加载的时机和顺序是由用户行为(如点击某按钮)控制的。其实这个特性是基于依赖于 Ext JS 4 的动态加载类的新特性的。详见"按需加载类"一节。
由此可见,运用MVC后HTML里不再直接写JS了,JS按逻辑、职责分门别类存于不同的目录,对应到不同的文件中。整体逻辑更加条理
入口定义在Ext.application({...})中,这是Ext JS 4为开发MVC应用新增的函数,我们可以在里面引入初始时所需的controller、view或model,在launch函数中编写初始代码,和以前在Ext.onReady()中一样。因为Ext引擎会在Ext.application({...})函数执行时创建一个全局application实例并能在controller中被引用得到 (this.application.*),所以我们也可以在application中定义一些公共函数,甚至注册一些事件,方便其它controller调用。
"model"文件夹中只有模型相关的类定义,每个模型定义必须包含字段,还能定义字段校验规则,不同模型之间的关联,以及数据代理 ( 连接服务器存取数据 )。比如雇员\部门对应两类模型,体现为两个类文件"Employee"和"Department"。
"view"文件夹中定义了所有的widget,每一个widget对应一个类文件。view的代码属于静态代码,后面将提到怎样用工具自动生成。
"controller"文件夹中的控制器按管理范围的不同划分为不同的类文件,其中每一个控制逻辑都包括初始化、组件事件监听以及引用等。比如,导航菜单的控制器会包含对主页面菜单按钮的动作监听”click“,并在该事件中负责创建相应的子页面;而子页面对应的控制器只负责该页面中的组件的行为,如提交按钮的点击等。另外控制器本身能被动态加载,在下文的例子中我们还可以看到,不同的控制器被加载的时机和顺序是由用户行为(如点击某按钮)控制的。其实这个特性是基于依赖于Ext JS 4的动态加载类的新特性的。详见"按需加载类"一节。
由此可见,运用MVC后HTML里不再直接写JS了,JS按逻辑、职责分门别类存于不同的目录,对应到不同的文件中。
开发Ext JS 4的利器:Sencha Architect
Sencha Architect是Sencha公司出品的一款辅助ExtJS开发的商业IDE软件,能帮助ExtJS开发人员更加专注于核心JS代码的开发,从而大大减少花费在编写界面、组织代码等反复性的工作上的时间。笔者写作时的工具版本是2.0.0 Build 412,此工具最大的特点是能帮助用户管理符合MVC模式的代码。例如,视图类代码能通过拖放组件结合属性设置的方式完全自动生成,不用写手一行代码。其它如Model、Store和Controller的代码能通过属性设置,方法、事件设置自动生成。理想情况下,一个熟练的ExtJS开发者在使用Sencha Architect时,百分之九十以上的时间会花在controller的实现和自定义组件(包括 override 一些组件)的开发。这一点也不夸张,因为在Sencha Architect中开发界面实在太轻松了。感兴趣的朋友可以从官网下载Sencha Architect的30天试用版尝尝鲜。
主要特性有:
通过拖放组件的方式生成复杂视图。
图 2.视图设计
设计好的视图,能方便切换到代码模式下预览,拷贝或导出。
图 3.模式切换
图 4.属性面板
图 5.导航面板
示例和代码
本文所指的入口代码是什么?
相信读者对Ext.onReady()不会陌生,本文所指的入口代码的功能与Ext.onReady() 是一样的,不同在于,新版的Ext JS 4将命名空间和全局application变量自然地融合在入口函数中,开发者很容易从Model、View或Controller中调用application中的函数、变量和事件,并从使用命名空间的过程中获益,使得MVC的开发变得更方便。
下面的示例程序是一个非常实用的集表单提交,表格应用和图表显示的综合运用的例子。由于篇幅限制,本文只列举主要的 JS 单元,感兴趣的朋友请到本文末尾处下载完整的示例程序。
本示例使用了默认的appFolder:app,实际中用户可以覆盖此属性,使用符合项目要求的路径名。我在项目中倾向于appFolder中的所有类由Sencha Architect工具维护,通过配置 mvn,在compile时将appFolder中生成的类拷贝到webApp中。手工维护的JS文件放在独立的命名空间中(称其为扩展空间吧),并在入口中声明,这样能被application引用并加载,同时在扩展空间的类也能 equire到application对应命名空间中的类,这样做的好处是,您能将override的代码移出来放到扩展空间中,另外还能放一些项目中用到的插件。
清单 3. 入口代码
清单 4.图表子页面控制器代码
图 6.表单
图 7.表格
图 8.图表
项目中的主要问题和解决办法
(1)此工具能生成几乎所有必须的代码,但对于手工编写的部分 JS 代码,本文推荐在 webApp 下建立独立的目录,并在入口文件中定义对应的路径到命名空间的映射。
(2)用编译工具如 mvn 将生成目录拷贝到 webApp 中。
(1)划分好Controller的范围和生命周期。
(2)划分好页面功能区,然后确定需要哪些Controller;区分哪些是动态的,比如一个子窗口或新页签,对应Controller的加载时机也应该是动态的。
(3)将需要动态加载的Controller从入口文件定义中移除。
(4)这样做的一个显而易见的好处是,避免初始页面"过载";另外能避免因init()调用太早导致事件绑定失败,原因也显而易见:需要绑定事件的组件还没有被创建出来。
设置过storeId的store将在storeManager中注册为单例;有时这是个限制,比如想在多个view实例中拥有独立的store时,Sencha Architect目前没有好的办法。办法有二,一是 override view,让每个view在create时拥有自己的store;二是在Model中设置proxy( 当然这时得移除 store 中的 proxy)。第二种方法来自Sencha的技术支持,但我还没试过。
我在使用Sencha Architect的时候碰到过这个问题,Architect能显示热数据,即属性设置好后,设计器能实时将数据作为预览显示出来;我一开始就碰到树不能显示的问题,接着是显示了又无法展开下级。
(1)设置好store的proxy中的idProperty、root属性。我一开始设置错了root(设置了一个不存在的 field),后来查了很久,找到了这个位置 , 问题解决。中间还怀疑是工具的 bug。 瞧,一个很不起眼的地方,但很打击士气。
(2)设置好树节点所用到的Model中的idProperty属性。这个属性决定点击树的节点往下钻取时往服务器传递的参数。
总结
Ext JS从4.0以后有了很大的变化,特别是增加了对MVC开发模式的支持,给Ext JS开发注入了新的活力,也极大地方便了大型WEB项目的开发。本文通过对使用MVC前后的比较,透过一个很实用的MVC实例,演示了运用Ext JS 4 MVC开发Web前端比用以前的版本要简单很多;文章最后,本人根据自己在开发过程中的经历提出了一些常见的困难以及解决办法。希望读者能从中得到一些启发和帮助。