本文适用于 Sencha Touch 2.x / ExtJS 4.x。
控制器,是一个完全将流程按面向对象方式设计的程序流程中的组件。例如,我们写最普通的PHP程序,页头包含 SESSION 模块,然后是访问控制。但若想,增加对主机名,子域名控制,则每一个包含的页面,都要再次增加包含之。或要么 在SESSION 模块,或要么在访问控制模块处增加一个包含文件。这样的话,程序逻辑将变得相当混乱。如果其中有出错与跳转,那么,势必会出现在不需要加载的页面跳来跳去。
控制器的目的,就是让页面请求最终到达所需要的页面。并且是基于面向对象的流程的。
通常:控制器,必须要有Host, SubDomain, IP,URL,ACL 的路由检测。由于现在一个网站,同时有浏览器与手机的,所以,还要有 UserAgent 检测。控制器才能做到最为方便地将一个请求映射到一个模块类的一个方法(事件)中。
控制器贯穿于应用程序整体,在代码上下文经常要访问控制器的引用。一个典型的应用程序起码不止一个控制器,多个控制器来实现程序内不同的功能。例如一个电子商务网站,将会有订单的控制器、顾客的控制器或产品的控制器等等。
全家对象 Ext.app.Application 的 controllers 配置项保存了 ST2 程序的所有控制器。控制器一般不经过程序员来实例化,而是在框架内部中由 Application 对象实例化并保存实例的引用,因此如果我们 new 一个控制器出来使用那便是多此一举。
首先要介绍的是控制器的一对“活宝”:refs 引用项 及 control。
Refs 其实就是组件选择符(ComponentQuery),相似的概念我们在 CSS Selector 样式选择符中见到过,输入查询条件来选择特定的元素从而与其他的元素区分开来。如同 CSS 拥有强大的 jQuery /Szzla 那般,这里的组件 refs 也有一个不俗的 ComponentQuery。通过相似的概念我们理解起来也就比较容易了。当然,我们单单只是获取了组件后没有用,还必须把我们动作逻辑与组件关联起来。怎么做?我们看看下面一个简单的例子,这是一个点击按钮然后登出的动作过程。
Ext.define('MyApp.controller.Main', { extend: 'Ext.app.Controller', config: { refs: { nav: '#mainNav' } }, addLogoutButton: function() { this.getNav().add({ text: 'Logout' }); } });从结构上看,我们所说的 ref 仅仅是 key/value 结构的一种。key 标识引用的名称,既然为名称那么任意您设置,比如这里 nav 是导航的意思;value 表示选择符(selector),选择哪个或哪些组件就是通过这个组件选择符。必须指明的是,组件选择符是 ST 创造概念,也许其他 JS 框架页会有,目的是为了方便程序获取特定的对象——但必须说明这不是一个适普性的概念,只有某些框架提供才会支持。比如这里的 #mainNav 就是一个组件选择符,那么框架会根据这个条件(标识 id 为 mainNav)查询符合条件的组件。
当我们需要访问这个组件的时候,可以通过 getNav() 函数获取组件。所有 refs 项都通过反射生成 getter/setter 方法,然后供程序员调用。这有存在一种默认的格式:总是用 get 开头,然后第一个字母变为大写,比如 nav --> getNav(),返回导航组件对象。
Ext.create('Ext.Toolbar', { id: 'mainNav', items: [ { text: 'Some Button' } ] });
像 nav : '#mainNav'这样,凭借组件的自身特征作为选择符条件使用的情形不是很多,更多的是在垂直方向写出组件层次定位组件,如“tabpanel panel[name=fish] infopanel”。