Sencha, the nightmare!
基础
创建一个应用程序
sencha -sdk /path/to/sdk generate app %name% /path/to/app
跑起来
cd /path/to/app
sencha app watch
放心,出错了会出红字,自己退回命令行。
开浏览器,默认地址是 http://localhost:1841
在 watch 模式下,任何对源程序的修改都会自动更新,方便马上看到效果。看起来还挺方便,但是因为过度的 js 对象化包装,使得 Sencha 的应用调试起来无比困难。生产化打包编译以后,更是只有一个 app.js,万一出错了的话,你是找不到源头的了。
目录结构
主要注意下面几个文件夹
app
与具体平台、设备分辨率无关的东东。比如下面要提到的数据模型、Store。
想法挺好,可是缺乏 IDE 支持的情况下(其自家的开发工具还不支持 6.0.2 版本的 Sencha),在各个目录之间跳转切换是非常麻烦的。即便用了 file buffer,你也得记住文件 id。
classic
经典 :) 听上去像极了 IIS Classic。就是传统的网页应用程序。写页面视图就在这里,也是默认的实现。
modern
现代,与经典对应。平板和触碰设备用。
packages
自定义的程序包,比如主题,就放在这里。默认的界面主题如果不能满足需要,那么就可以自定义主题。虽然自定义是非常痛苦的。
resources
图片,通用的文件放在这里。
数据
Model
模型,或者叫数据模型,可以看作数据库存储的结构映射。
定义一个数据模型,继承自 Ext.data.Model
Ext.define("Inventory.model.Band",{ extend:'Ext.data.Model', fields:[ {name:'Id', type:'int'}, {name:'Start', type:'float',allowBlank:false }, {name:'End', type:'float',allowBlank:false}, {name:'Wavelength', type:'string',allowBlank:false } ]});
顺便说一句,用不同文件夹来存放同一个功能模块各个不同组件的做法非常落后。这本是用 IDE 和命名规范可以轻易解决的问题。而在类名里面加上文件夹的结构,则更是多余:多继承或者引用、实现抽象类的时候,多个文件夹结构你怎么放、怎么起名?
Store
存储。其实是存储代理的定义,即,从哪儿读取数据,又将数据写回哪儿。
其 load 函数在数据读取完成后回调,可以对返回的数据做进一步处理,比较方便。需要绑定数据模型使用。
proxy 属性指明了实际进行数据库(存取)操作的服务地址,这里也就出了 Sencha 的圈儿了,Spring 也可以、ASP.NET 也可以,随意。
Ext.create('Ext.data.Store',{ model:'Inventory.model.Band', id:'remotestore', proxy:{ type : 'rest', url:'http://localhost:40544/Band.svc/GetBands', reader : { type : 'json', rootProperty : 'd' } }, listeners:{ load:function ( pageStore, records, successful , pageOperation , eOpts ){ var bs = {bands:[]}; for(var i=0;i<records.length;i++){ bs.bands.push(records[i].data); } Ext.getStore('bandstore').setData(bs); } }});
ViewModel
视图模型,即对页面上所放字段的映射。可以是数据模型的一部分,也可以是多个关联数据模型的组合。但其实 Sencha 这么搞,是把简单问题弄复杂了,因为 html 页面本身就有表单和字段,直接 parse 其键值对即可;而现在则必须再重新定义一遍这些字段,等于同样的定义在 html 表单和模型视图里面各自写了一遍,重复了。
定义一个视图模型
Ext.define('Inventory.view.main.MainModel', { extend: 'Ext.app.ViewModel', alias: 'viewmodel.main', data: { name: 'Inventory' }});
使用的时候,首先在页面里面说明要用到的视图模型是哪个,然后对页面上可以 set 的属性绑定视图模型的字段,比如下面这个,绑定页面的标题:
viewModel: 'main',header: { title: { bind: { text: '{name}' } }}
视图
放在页面上的可视区域,用来显示内容、提供交互操作。类似 SharePoint 上面的 WebPart。但是 WebPart 的本意是让用户也可以自定义页面(这个想法也是挺天真),视图则是让程序员来自定义页面(这个想法更是天真)。
创建一个新视图,名字叫 band.Band,但是放在 main 文件夹里面。这就是我前面说的,文件夹归类法不靠谱的地方。
Ext.define('Inventory.view.band.Band', { extend: 'Ext.panel.Panel', xtype: 'bandview', items :[ {html:'<h2>hello!</h2>'} ]});
我们也可以用之前定义的视图模型来动态地显示点儿内容:
Ext.define('Inventory.view.band.Band', { extend: 'Ext.panel.Panel', xtype: 'bandview', viewModel: 'main', items :[ {bind:{html:'<h2>hello,{name}!</h2>'}} ]});